async和await

531 阅读2分钟

小结

await后面接一个会return new promise的函数并执行它
await只能放在async函数里

什么是async

ES7 提出的async 函数,终于让 JavaScript 对于异步操作有了终极解决方案。No more callback hell。
async 函数是 Generator 函数的语法糖。使用 关键字 async 来表示,在函数内部使用 await 来表示异步。
想较于 GeneratorAsync 函数的改进在于下面四点:
- **内置执行器**。Generator 函数的执行必须依靠执行器,而<font color=#A52A2A>Aysnc</font>函数自带执行器,调用方式跟普通函数的调用一样
- **更好的语义**。asyncawait 相较于 * 和 yield 更加语义化
- **更广的适用性**。co 模块约定,yield 命令后面只能是 Thunk 函数或 Promise对象。而 async 函数的 await 命令后面则可以是 Promise 或者 原始类型的值(Numberstringboolean,但这时等同于同步操作)
- **返回值是 Promise**。async 函数返回值是 Promise 对象,比 Generator 函数返回的 Iterator 对象方便,可以直接使用 then() 方法进行调用

如何使用async

结果必须return,不然值都为undefined, 建议使用箭头函数
可以return各种数据类型的值,皆为resolve
但是返回如下结果,则判定失败reject
1. 内部含有直接使用未声明的变量或函数
2. 内部抛出一个错误throw new Error 或者返回reject状态 return Promise.reject('执行失败')
3. 函数方法执行错误

什么是await

await意思是async wait(异步等待)。这个关键字只能在使用async定义的函数里面使用。
任何async函数都会默认返回promise,并且这个promise解析的值都将会是这个函数的返回值,而async函数必须等到内部所有的 await 命令的 Promise 对象执行完,才会发生状态改变。
正常情况下,await 命令后面跟着的是 Promise ,如果不是的话,也会被转换成一个 立即 resolve 的 Promise
async function testSometing() {
    console.log("testSomething");
    return "return testSomething";
}

async function testAsync() {
    console.log("testAsync");
    return Promise.resolve("hello async");
}

async function test() {
    console.log("test start...");

    const testFn1 = await testSometing();
    console.log(testFn1);

    const testFn2 = await testAsync();
    console.log(testFn2);

    console.log('test end...');
}

test();

var promiseFn = new Promise((resolve)=> { 
    console.log("promise START...");
    resolve("promise RESOLVE");
});
promiseFn.then((val)=> console.log(val));

console.log("===END===")

结果:
test start...
testSomething
promise START...
===END===
return testSomething
test end...
testAsync
promise RESOLVE
hello async
1. 执行test(), 先输出"test start..."
2. 声明函数await testSometing(),先执行console.log("testSomething")输出,后跳出test(),执行后面代码
3. 执行promiseFn,输出"promise START...",遇Promise,放置Promise队列第一位,跳出函数,向下执行
4. 输出"===END===",返回test(),继续执行console.log(testFn1),testSometing()被调用,输出"return testSomething"
5.声明函数await testAsync(),先执行console.log("testAsync")输出,后跳出test(),执行后面代码
6. 这时需要执行之前的Promise队列第一位,输出"promise RESOLVE",返回test(),继续执行console.log(testFn2),testAsync()被调用,遇Promise,放置当前Promise队列第一位,因当前没有其他代码执行,故输出"hello async"
7. 最后输出"test end..."