基本概念
Async实际上是一个封装了自动化执行并返回一个Promise的Generator函数的语法糖。这句话的意思我们可以分为三个部分来解读:
-
首先它有一个自动化执行,Generator函数是依靠不停的调用.net来依次执行的,Async有一个自动化执行的过程。
-
第二个,它返回一个Promise,也就是说在Async函数里面我们拿到它的结果需要调用promise.then。
-
Generator函数的语法糖。
不添加自动化执行脚本的函数:
function resolveAfter2Seconds(value) { return new Promise(resolve => { setTimeout(() => { resolve(value); },2000); }) } const generator = function* () { const value1 = yield resolveAfter2Seconds(1); const value2 = yield resolveAfter2Seconds(2); console.log(value1); console.log(value2); };
Generator自动化执行的脚本:
function co(generatorFunction){ return new Promise(function(resolve, reject) { const generator = generatorFunction(); function step(nextF) { let next; try { next = nextF(); } catch(e) { return reject(e); } // 如果遍历已经结束了 if(next.done) { return resolve(next.value); } Promise.resolve(next.value).then(function(v) { step(function() { return generator.next(v); }); },function(e) { step(funciton() { return generator.throw(e); }); }); } step(function() { return generator.next(undefined); }); }); } co(generator); /* (4s后) 1 2 */ const async = async function () { const value1 = await resolveAfter2Seconds(1); const value2 = await resolveAfter2Seconds(2); console.log(value1); console.log(value2); }; async().then(res => { console.log(res); }) /* (4s后) 1 2 */ async function asyncFunc() {}; const asyncFunc = async function () {}; const asyncFunc = async () => {}; const obj = { async asyncFunc() {} }
语法
-
首先,最重要的一点是它返回一个Promise对象,也就是说,在Async里面,在它后面我们想要得到函数的执行结果,必须使用一个.then()。
async function asyncGun() { return 'Eric'; } asyncFunc().then(value => console.log(value)); // Eric
-
第二个,await遇到了一个非Promise,直接返回:
async function asyncFunc(){ return await 'Eric'; } asyncFunc().then(value => console.log(value)); // Eric
-
thenable(带有then方法的一个函数)对象等同于Promise。
class Thenable { constructor(timeout) { this.timeout = timeout; } then(resolve, reject) { setTimeout{ () => resolve('resolve'), this.timeout }; } }
-
Async函数任何一个await返回reject,那么就会导致整个Async的中断执行。
promise.all(),只有当它内部所有的子promise全部reslove时,整个promise才会resolve,只要有一个reject,那么整个promise.all就会reject,aysnc同样的原理。
注意事项
-
尽量使用try...catch代码块,因为一旦用到了Async,显然这个场景肯定是有多个不方便操作的,这个时候为了防止中间出错,最好使用一个try...catch 的代码块,然后在catch代码块的内部加上我们的一些备用数据。
-
非继发的await同时执行,继发就是一个接一个也就是前面一个函数的输出是后面一个函数的输入,类似于函数式编程里面的compose。 对于继发的我们没有办法只能等待前面的操作完再去执行后续操作。
function resolveAfter2Seconds(value){ return new Promise(resolve => { setTimeout(() => { resolve(value); },2000); }); }; const async = async function(){ const value1 = await resolveAfter2Seconds(1); const value2 = await resolveAfter2Seconds(2); console.log(value1); console.log(value2); }; async().then(res => {}) // 4s 后输出 1 2
怎么样才能让两者同步执行,可以有两种办法。 第一种,使用Promise.all()将它封装起来:
function resolveAfter2Seconds(value){ return new Promise(resolve => { setTimeout(() => { resolve(value); },2000); }); } const async = async function() { const [value1,value2] = await Promise.all([resolveAfter2Seconds(1), resolveAfter2Seconds(2)]) console.log(value1); console.log(value2); }; async().then(res => {}); // 2s后输出 1 2
第二种,先执行再await,也就是把异步的一个操作赋值给一个变量:
function resolveAfter2Seconds(value){ return new Promise(resolve => { setTimeout(() => { resolve(value); },2000); }); } const async = async function() { const vpromise1 = resolveAfter2Seconds(1); const vpromise2 = resolveAfter2Seconds(2); const value1 = await vpromise1; const value2 = await vpromise2; console.log(value1); console.log(value2); } async().then(res => {}); // 2s 后输出 1 2