一次性让你懂async/await,解决回调地狱

发布时间 2023-07-01 12:08:51作者: 窦戈

终极思想

  • 如果它等到的不是一个 Promise 对象,那 await 表达式的运算结果就是它等到的东西。
  • 如果它等到的是一个 Promise 对象,await 就忙起来了,它会阻塞后面【阻塞的只是当前路径,并不阻塞其它路径的代码】的代码,等着 Promise 对象 resolve,然后得到 resolve 的值,作为 await 表达式的运算结果。

示例一

代码

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===")

运行结果

运行解说

  1. 首先test()打印出test start...
  2. 然后 testFn1 = await testSomething(); 的时候,会先执行testSometing()这个函数打印出“testSometing”的字符串。
  3. testAsync()执行完毕返回resolve,之后await会让出线程就会去执行后面的,触发promiseFn打印出“promise START...”。
  4. 接下来会把返回的Promiseresolve("promise RESOLVE")放入Promise队列(Promise的Job Queue),继续执行打印 “=== END ===”。
  5. 等本轮事件循环执行结束后,又会跳回到async函数中(test()函数),等待之前await 后面表达式的返回值,因为testSometing() 不是async函数,所以返回的是一个字符串“return``testSometing”。
  6. test()函数继续执行,执行到testFn2(),再次跳出test()函数,打印出“testAsync”,此时事件循环就到了Promise的队列,执行promiseFn.then((val)=> console.log(val));打印出“promise RESOLVE”。
  7. 之后和前面一样 又跳回到test函数继续执行console.log(testFn2)的返回值,打印出“hello async”。
  8. 最后打印“test end...”。

示例二

加点料,让testSomething()变成async

代码

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===")

运行结果

运行解说

和上一个例子比较发现promiseFn.then((val)=> console.log(val)); 先于console.log(testFn1) 执行。
原因是因为现在的版本async函数会被await resolve,

补充

function testSometing() {
    console.log("testSomething");
    return "return testSomething";
}
console.log(Object.prototype.toString.call(testSometing)) // [object Function]
console.log(Object.prototype.toString.call(testSometing())) // [object String]

async function testSometing() {
    console.log("testSomething");
    return "return testSomething";
}
console.log(Object.prototype.toString.call(testSometing)) // [object AsyncFunction]
console.log(Object.prototype.toString.call(testSometing())) // [object Promise]

testSomething()已经是async函数,返回的是一个Promise对象需要等它 resolve 后将当前Promise 推入队列,随后先清空调用栈,所以会"跳出" test() 函数执行后续代码,随后才开始执行该 Promise。