js中promise学习

作者: 正阳Android | 来源:发表于2019-01-13 23:15 被阅读0次

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8">

<title>promise学习</title>

<!-- 在js中,所有代码都是单线程执行的 -->

<!-- 异步执行:可以使用回调,在ES6中我们可以使用Promise对象来实现 -->

<!--

1.1Promise对象,只需要then一个方法,then方法带有如下三个参数

    1.成功回调

    2.失败回调

    3.前进回调(暂时不讲)

    一个全新的 promise 对象从每个 then 的调用中返回。

1.2 Promise对象代表一个异步操作,其不受外界影响,有三种状态

.Pending进行中

.Resolved(已完成,又称Fulfilled)

.Rejected(已失败)

1.3使用Promise的优势

1.3.1 解决回调地狱问题(Callback Hell)

例如,有时候我们可能会进行多个异步操作,后一个的请求需要上一次请求的返回结果,所以过去我们都是用callback层层嵌套,

但是多了的话就会出现回调地狱,代码的可读性和维护性都会变得很差

firstAsync(function(data){

                        //处理得到的 data 数据

//....

secondAsync(function(data2){

//处理得到的 data2 数据

//....

thirdAsync(function(data3){

  //处理得到的 data3 数据

  //....

});

});

});

1.3.2 使用promise的话,代码会变得扁平和可读.前面提到了then返回一个promise,因此我们可以将then的调用不停的串联起来,其中then返回的

promise装载了由调用返回的值.

firstAsync()

.then(function(data){

//处理得到的 data 数据

//....

return secondAsync();

})

.then(function(data2){

//处理得到的 data2 数据

//....

return thirdAsync();

})

.then(function(data3){

//处理得到的 data3 数据

//....

});

1.3.3 更好的进行错误捕获

多层嵌套会造成无法捕获异常,使用promise,通过使用reject方法把promise的状态设置为rejected,这样我们在then中就能捕捉到,然后执行失败情况的回调

function fetch(callback) {

return new Promise((resolve, reject) => {

setTimeout(() => {

reject('请求失败');

}, 2000)

})

}

fetch()

.then(

function(data){

console.log('请求处理');

console.log(data);

},

function(reason, data){

console.log('触发异常');

console.log(reason);

}

);

当然我们在catch方法中处理reject回调也是可以的,

function fetch(callback) {

return new Promise((resolve, reject) => {

setTimeout(() => {

reject('请求失败');

}, 2000)

})

}

fetch()

.then(

function(data){

console.log('请求处理');

console.log(data);

}

)

.catch(function(reason){

console.log('触发异常');

console.log(reason);

});

-->

</head>

<body>

<script type="text/javascript">

new Promise(function(resolve, reject) {

console.log('start new Promise...');

var timeOut = Math.random() * 2;

console.log('set timeout to: ' + timeOut + ' seconds.');

setTimeout(function() {

if (timeOut < 10) {

console.log('call resolve()...');

resolve('200 OK');

} else {

console.log('call reject()...');

reject('timeout in ' + timeOut + ' seconds.');

}

}, timeOut * 1000);

}).then(function(r) {

console.log('Done: ' + r);

}).catch(function(reason) {

console.log('Failed: ' + reason);

});

// promise的使用详解,简单来讲,then方法就是把原来的回调写法分离出来,在异步执行操作执行完成后,用链式调用的方式,回调函数;

// 我们可以在then方法中继续写promise对象并返回,然后继续调用then进行回调操作

// then方法举例          例如 学习 考试  放假

function study() {

var p = new Promise(function(resolve, reject) {

setTimeout(() => {

resolve("学习结束,开始考试")

}, 2000)

});

return p;

}

function test(data) {

var p = new Promise(function(resolve, reject) {

setTimeout(() => {

resolve("考试结束,开始假期")

}, 2000)

});

return p;

}

function holiday(data) {

var p = new Promise(function(resolve, reject) {

setTimeout(() => {

resolve("假期结束,开始上课")

}, 2000)

});

return p;

}

// 使用then链式调用这三个方法

study()

.then(function(data) {

console.log(data)

return test(data);

})

.then(function(data) {

console.log(data)

return holiday(data)

})

.then(function(data) {

console.log(data)

})

// 运行结果

// 学习结束,开始考试

// 试结束,开始假期

// 假期结束,开始上课

// 2.reject方法

function learn() {

var p = new Promise(function(reslove, reject) {

setTimeout(() => {

reject("考试不及格")

}, 1000)

});

return p;

}

learn()

.then(test, function(data) {

console.log(data + "无法放假,复习吧");

})

// 执行结果

// 考试不及格无法放假,复习吧

// 另外如果我们只要处理失败的情况,可以使用then(null,.....),或者使用catch方法

learn()

.then(null, function(data) {

console.log(data + "无法放假,复习吧");

})

// catch方法和then方法的第二个参数一样,用来指定reject的回调

learn()

.then(test)

.catch(function(data) {

console.log("没得玩了");

})

// 另一个作用是,当执行resolve的回调时,如果抛出了异常(代码出错),那么也不会报错卡死js,而是会进到这个catch中

study()

.then(function(data) {

throw new Error("考题泄漏");

test(data)

})

.catch(function(data) {

console.log(data + "无法继续考试")

})

// all方法,提供了并行异步执行操作的能力,并且在所有异步操作执行完后才会执行回调

// 例如放假要等到学习和考试之后

setTimeout(() => {

Promise.all([study(), test(),holiday()])

.then(function(data) {

console.log("开始放假了:后面的是data数据  "+data.length+"第一个:"+data[0]+"第二个:"+data[1]+"第三个:"+data[2])

// 打印结果:  开始放假了:后面的是data数据  3第一个:学习结束,开始考试第二个:考试结束,开始假期第三个:假期结束,开始上课

})

}, 1000)

// race方法,用法与all一样,只是all是等所有的异步操作完成之后,才会执行then回调.而race回调的话只要有一个异步操作执行完毕,就立刻执行then回调;

//then方法里面的回调中的参数data是一个数组,我们可以得到异步执行操作的结果

// PS:其他没有执行完毕的异步操作,仍然会继续执行,而不是停止

setTimeout(() => {

Promise.race([study(), test()])

.then(function(data) {

console.log("考试不考试,学习不学习,都没关系的")

})

}, 20000)

// race的使用场景很多,例如我们可以给某一个race设置请求超时时间

//考研开始,5s内交卷认为合格,否则认为不合格

function passTheExam() {

var p = new Promise(function(resolve, reject) {

setTimeout(() => {

resolve("交卷")

}, 25000);

})

return p;

}

function requestTimeOut() {

var p = new Promise(function(resolve, reject) {

setTimeout(() => {

reject("考试失败")

}, 30000);

})

return p;

}

Promise.race([passTheExam(),requestTimeOut()])

.then(function(data){

console.log(data);

})

.catch(function(err){

console.log(err);

})

</script>

</body>

</html>

相关文章