异步处理promise 、Generator与 async await

前端开发中会遇到某些场景存在异步问题,比如从后端请求到数据以后才能继续往下执行某函数,最常见的写法是将函数调用写在请求数据的回调函数里,待请求函数执行完毕后再执行下面的函数,但是此方法有一弊端就是若业务逻辑太过复杂时,会一层层使用回调 ,使得代码可读性与维护性变得很差(回调地狱)。

promise:es6提供了原生的promise对象,promise对象代表了未来将要发生的事件,用来传递异步操作的消息

两个特点:

1、不受外界影响,代表一个异步操作,有三种状态:pending(初始状态非成功与失败状态),fulfilled(操作成功状态),rejected(失败状态)

2、一旦状态改变就不会再变:只有两种情况,从pending变为resolveed或者从pending变为rejected状态,只要发生就不再改变

优缺点:优点是避免了层层嵌套的回调函数, promise对象还提供了提供了统一的接口,使控制异步操作更加容易

缺点是无法取消Promise,一旦新建就必须完成,若不设置回调函数,promise内部返回的错误就不会反应到外部,当处于pending状态时,无法得知目前进行到了那个阶段

promise的创建:


已经实例化过的对象可以调用promise.then方法,传递resove方法和reject方法作为回调

promise.then(onFulfilled, onRejected);promise简化了错误处理的方法,我们也可以这样写:promise.then(onFulfilled).catch(onRejected)

链式操作:Promise.prototype.then返回的是一个新的Promise对象,因此可以采用链式写法


Promise链式操作可以使异步函数按特定顺序执行,一定程度上避免了回调地狱,代码可读性与可维护行提高

Promise.proptype.catch方法捕捉错误:

Promise.prototype.catch 方法是 Promise.prototype.then(null, rejection) 的别名,用于指定发生错误时的回调函数。

Promise 对象的错误具有"冒泡"性质,会一直向后传递,直到被捕获为止。也就是说,错误总是会被下一个 catch 语句捕获。

Promise.all方法:Promise.all 方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。

var p = Promise.all([p1,p2,p3]);

上面代码中,Promise.all 方法接受一个数组作为参数,p1、p2、p3 都是 Promise 对象的实例。(Promise.all 方法的参数不一定是数组,但是必须具有 iterator 接口,且返回的每个成员都是 Promise 实例。)

p 的状态由 p1、p2、p3 决定,分成两种情况。

(1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。

(2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。

Promise.race 方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。

var p = Promise.race([p1,p2,p3]);

上面代码中,只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的Promise实例的返回值,就传递给p的返回值。

Generator:ES6 新引入了 Generator 函数,可以通过 yield 关键字,把函数的执行流挂起,为改变执行流程提供了可能,从而为异步编程提供解决方案。

Generator 有两个区分于普通函数的部分:

一是在 function 后面,函数名之前有个 * ;

函数内部有 yield 表达式。

其中 * 用来表示函数为 Generator 函数,yield 用来定义函数内部的状态。

执行机制

调用 Generator 函数和调用普通函数一样,在函数名后面加上()即可,但是 Generator 函数不会像普通函数一样立即执行,而是返回一个指向内部状态对象的指针,所以要调用遍历器对象Iterator 的 next 方法,指针就会从函数头部或者上一次停下来的地方开始执行。

除了使用 next ,还可以使用 for... of 循环遍历 Generator 函数生产的 Iterator 对象。
return 方法返回给定值,并结束遍历 Generator 函数。return 方法提供参数时,返回该参数;不提供参数时,返回 undefined 。

throw 方法:


throw 方法可以再在Generator 函数体外面抛出异常,在函数体内部捕获。遍历器对象抛出了两个错误,第一个被 Generator 函数内部捕获,第二个因为函数体内部的catch 函数已经执行过了,不会再捕获这个错误,所以这个错误就抛出 Generator 函数体,被函数体外的 catch 捕获。


yield* 表达式表示 yield 返回一个遍历器对象,用于在 Generator 函数内部,调用另一个 Generator 函数。使用场景实现 Iterator为不具备 Iterator 接口的对象提供遍历方法。


async方法

async 是 ES7 才有的与异步操作有关的关键字,和 Promise , Generator 有很大关联的。

async 函数返回一个 Promise 对象,可以使用 then 方法添加回调函数

async 函数中可能会有 await 表达式,async 函数执行时,如果遇到 await 就会先暂停执行 ,等到触发的异步操作完成后,恢复 async 函数的执行并返回解析值。

注意await的函数返回的是一个Promise对象,所以必须要将异步函数写到Promise对象里,await 操作符用于等待一个 Promise 对象, 它只能在异步函数 async function 内部使用。

返回值:返回 Promise 对象的处理结果。如果等待的不是 Promise 对象,则返回该值本身。

如果一个 Promise 被传递给一个 await 操作符,await 将等待 Promise 正常处理完成并返回其处理结果。

await针对所跟不同表达式的处理方式:Promise 对象:await 会暂停执行,等待 Promise 对象 resolve,然后恢复 async 函数的执行并返回解析值。非 Promise 对象:直接返回对应的值。

await 命令后面是一个 Promise 对象,它也可以跟其他值,如字符串,布尔值,数值以及普通函数。

本文部分内容参考自菜鸟教程ES6教程

你可能感兴趣的:(异步处理promise 、Generator与 async await)