async/await执行机制
async和await其实是Promise和Ganerator函数的语法糖
- 用async关键字修饰一个函数,会使这个函数内部可以使用await关键字
- await 操作符用于等待一个Promise 对象。它只能在异步函数 async function 中使用
- 如果await后面跟着的不是一个Promise对象,会自动将其变为Promise对象执行
- 遇到await关键字,会立即执行跟在await后面的代码,然后将await下方的代码变成一个微任务,加入到webAPI中进行监听,等待状态改变后加入到EventQueue中等待执行
需求:ajax并行和串行
模拟数据请求
// 模拟数据请求
const query = interval => {
return new Promise(resolve => {
setTimeout(() => {
resolve(interval);
}, interval);
});
};
query(1000).then(value => {
console.log('第一个请求成功', value);
});
query(2000).then(value => {
console.log('第二个请求成功', value);
});
query(3000).then(value => {
console.log('第三个请求成功', value);
});
- 并行:同时发送多个请求,多个请求之间没有依赖「一般我们会等待所有请求都成功,整体做个啥事…」
Promise.all([query(1000), query(2000), query(3000)]).then(values => {
console.log('三个请求都成功', values);
});
- 串行:多个请求之间是有依赖的,第一个请求成功,才能发送第二个请求,第二个请求成功,才能发送第三个…
- 方案一:使用Promise「解决回调地狱问题」
query(1000).then(value => { console.log('第一个请求成功', value); return query(2000); }).then(value => { console.log('第二个请求成功', value); return query(3000); }).then(value => { console.log('第三个请求成功', value); });
- 方案二:使用generator
function* generator() { let value; value = yield query(1000); console.log('第一个请求成功', value); value = yield query(2000); console.log('第二个请求成功', value); value = yield query(3000); console.log('第三个请求成功', value); } let itor = generator(); //第一次执行返回一个对象,对象的value是一个promise实例 // itor.next().value 每一次执行next遇到yield结束,发送一个请求,value获取的是promise实例 itor.next().value.then(value => { // value第一次请求的结果,第二次执行next的时候,需要把这个结果传递给next,作为第一次yeild的返回值 itor.next(value).value.then(value => { // value第二次请求的结果 itor.next(value).value.then(value => { // value第三次请求的结果 itor.next(value); }); }); });
- 方案三:我们把next一层层嵌套的逻辑,自动管理起来 「插件:co.js就是这样封装的」
- generator传递的生成器函数「基于yield管理每一个要发送的请求」
- params存储的是:后期把generator执行,传递给他的实参
模拟async/await机制实现
const AsyncFunction = function AsyncFunction(generator, ...params) {
return new Promise((resolve, reject) => {
let itor = generator(...params);
const next = x => {
let {
value,
done
} = itor.next(x);
if (done) {
// 所有请求都成功,则返回一个状态是成功的promise实例
resolve(value);
return;
}
if (!isPromise(value)) value = Promise.resolve(value);
value.then(result => next(result))
.catch(reason => {
// 其中有一个请求失败,则返回一个状态是失败的promise实例
reject(reason);
itor.throw(reason);
});
};
next();
});
};
AsyncFunction(function* generator() {
let value;
value = yield query(1000);
console.log('第一个请求成功', value);
value = yield Promise.reject('xxx');
console.log('第二个请求成功', value);
value = yield query(3000);
console.log('第三个请求成功', value);
return 'hhh';
}).then(value => {
console.log(`所有请求都成功`, value);
}).catch(reason => {
console.log(`某个请求失败`, reason);
});
真实项目使用async/await处理
- 我们上面基于 promise + generator + AsyncFunction函数,实现的就是async/await的处理机制
- async/await是 promise + generator 的语法糖
(async function () {
let value;
try {
value = await Promise.reject('xxx');
console.log('第一个请求成功', value);
} catch (err) {
console.log(err);
}
value = await query(2000);
console.log('第二个请求成功', value);
value = await query(3000);
console.log('第三个请求成功', value);
})();