零. 处理异步常见方法
- 回调函数
- 事件监听
- 发布/订阅
- promise
- generator函数
- async/await
一. Promise (解决回调函数多重嵌套)
Promise对象代表一个异步操作,有三种状态,pending(操作中),resolved(已完成),rejected(失败)
状态改变只有两种,pending -》resolved 和pending -》rejected
状态一旦改变就不会更改
Promise构造函数
- Promise构造函数传入resolve和reject两个方法, 返回一个promise对象
- resolve函数将promise对象将pending状态转为resolved状态,在异步操作成功时调用,将异步操作结果作为参数传递出去
- reject函数将promise对象将pending状态转为rejected状态,在异步操作失败时调用,将异步操作错误作为参数传递出去
- promise对象 可用then方法指定resolved状态回调 和rejected状态回调
- 优点:异步操作变成链式调用,类似同步书写的逻辑
缺点:无法取消promise;处于pending状态,无法知道进展到什么程度(操作刚开始还是操作快完成)
var promise = new Promise(resolve, reject){
...
if(/*异步操作*/){
resolve(value)
}else{
reject(error)
}
}
promise.then(function(value){}, function(error){})
二. generator函数
调用并不立即执行,返回一个指向内部状态的指针对象
调用next() 指针移到下一个状态
- 即从函数头部或者上次暂停的地方开始,直到遇到下一个yield表达式或者return语句为止
- next() 返回一个对象{value:yield表达式的值,done: true/false}
- value属性值为当前yield表达式的值,done属性值为布尔值,表示遍历是否结束
- 异步应用
var f = function* (){
...
yield fetch // yield $.ajax 返回一个promise对象
}
f.next().value.then(data => {
})
- CO模块对generator生成器函数封装
function co (gen){
var it = gen();
var ret = gen().next()
ret.value.then(function(res){
it.next(res)
})
}
// 调用传入生成器
co(function* (){
var data = yield $.get('api/data');
console.log(data);
var user = yield $.get('api/user');
console.log(user);
})
三. async/await(es2017 generator函数语法糖)
自带执行器,自动执行,不像generator需要调用 next()
函数执行时,遇到 await 先返回,等异步操作完成
await 后面紧跟任意表达式的结果
如果 await 等到的不是一个 promise 对象,则 await 表达式的结果就是它等到的东西
如果 await 等到的是一个 promise 对象,await 会等待这个 Promise 完成,并将其 resolve 的结果返回出来异步应用
async function (){
...
await ...
}