ES6的异步操作之promise用法和async函数的具体使用

promise 基本用法

Promise 对象是一个构造函数,用来生成 Promise 实例。Promise 构造函数接受一个函数作为参数,该函数的两个参数分别是 resolve 和 reject。

resolve 函数的作用是,在异步操作成功时调用(Promise 对象的状态从 pending 变为 fulfilled),并将异步操作的结果,作为参数传递出去。

reject 函数的作用是,在异步操作失败时调用(Promise对象的状态从 pending 变为 rejected),并将异步操作报出的错误,作为参数传递出去。

const funPromise = function(options) { return new Promise(function(resolve, reject) { if (/* 异步操作成功 */){ resolve(result); } else { reject(error); } }); }

resolve 函数的参数除了正常的值以外,还可能是另一个 Promise 实例,此时,初始 promise 的最终状态根据传入的新的 Promise 实例决定。

reject 方法的作用,相当于抛出错误。等同于 throw new Error('error')。

Promise.prototype.then()

Promise 实例具有 then 方法,它的作用是为 Promise 实例添加状态改变时的回调函数,即 Promise 实例生成以后,用 then 方法分别指定 fulfilled 状态和 rejected 状态的回调函数。

funPromise().then(function(result) { // fulfilled }, function(error) { // rejected })

then 方法可以接受两个回调函数作为参数。第一个回调函数是 Promise 对象的状态变为 fulfilled 时调用,第二个回调函数是 Promise 对象的状态变为 rejected 时调用。其中,第二个函数是可选的,不一定要提供。这两个函数都接受 Promise 对象传出的值作为参数。

then 方法返回的是一个新的 Promise 实例(注意,不是原来那个 Promise 实例)。因此可以采用链式写法,即 then 方法后面再调用另一个 then 方法来处理上一个 then 方法中 return 的结果。

funPromise().then(function(result) { return result.data; }).then(function(data) { // fulfilled });

上面的代码使用 then 方法,依次指定了两个回调函数。第一个回调函数完成以后,会将返回结果作为参数,传入第二个回调函数。并且,第一个 then 返回的结果也可以是另一个异步操作的 Promise 对象,这时后一个 then 函数,就会等待该 Promise 对象的状态发生变化,才会被调用。

funPromise().then( (result) => { return funPromise(result); } ).then( (data) => { /* fulfilled */ }, (error) => { /* rejected */ } );

上面代码中,第一个 then 方法指定的回调函数,返回的是另一个 Promise 对象。这时,第二个 then 方法指定的回调函数,就会等待这个新的 Promise 对象状态发生变化。如果变为 fulfilled,就调用第一个回调函数,如果状态变为 rejected,就调用第二个回调函数。

Promise.prototype.catch()

Promise 实例具有 catch 方法,它的作用是为 Promise 实例添加状态改变为 rejected 状态的回调函数,也就是 then 方法的第二个函数的替代写法。

funPromise().then(function(result) { // fulfilled }).catch(function(error) { // 处理 funPromise 和之前 then 回调函数运行时发生的错误 });

Promise 对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止。也就是说,无论前面有多少个 then 函数,其中的错误总是会被下一个 catch 语句捕获。

funPromise().then(function(result) { return funPromise(result); }).then(function(data) { // fulfilled }).catch(function(error) { // 处理前面三个 Promise 产生的错误 });

一般来说,不要在 then 方法里面定义 rejected 状态的回调函数(即 then 的第二个参数),总是使用 catch 方法,因为这种写法可以捕获前面 then 方法执行中的错误。

catch 方法返回的还是一个 Promise 对象,并且 catch 中如果没有抛出任何其它错误,那么该 Promise 对象则是 resolved 状态。而且后面还可以接着调用 then 方法,但是前面的 catch 不能捕获后面的 then 中的错误,所以尽量 catch 都写在最后。

Promise.all()

Promise.all() 方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。其接受一个数组作为参数,数组中的值都是 Promise 实例,如果不是,就会先调用 Promise.resolve() 方法,将参数转为 Promise 实例,再进一步处理。

const p = Promise.all([funPromise(1), funPromise(2), funPromise(3)]);

p 的状态由数组中的值决定,分成两种情况。

数组中 Primise 实例的状态都变成 fulfilled,p 的状态才会变成 fulfilled,此时数组中实例的返回值组成一个数组,传递给 p 的回调函数。

只要数组的实例之中有一个被 rejected,p 的状态就变成 rejected,此时第一个被 reject 的实例的返回值,也就是报错信息,会传递给 p 的回调函数。

p.then(function (results) { // 全部 fulfilled,results 是个数组,里面是每个实例的返回结果 }).catch(function(error){ // 其中有一个变为 rejected });

注意,如果作为参数的 Promise 实例,自己定义了 catch 方法,那么它一旦被 rejected,并不会触发 Promise.all() 的 catch 方法。

应用

用 Promise 对象实现 Ajax。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/2afb896323adea13899c2543d39ac155.html