Promise、async、setTimeout异步执行顺序问题

    技术2024-07-17  83

    题目一:

    console.log('script start'); setTimeout(function() { console.log('setTimeout'); }, 0); const newPromise6 = new Promise(function(resolve, reject) { resolve(console.log('promise1')); }); newPromise6.then(function() { console.log('promise2'); }).then(function() { console.log('promise3'); }); console.log('script end');在chrome中输出结果?

    结果: script start promise1 script end promise2 promise3 setTimeout

    解析: 异步任务之间,会存在差异,所以它们执行的优先级也会有区别。 大致分为 微任务(microtask,如:Promise、MutaionObserver等)和 宏任务(macrotask,如:setTimeout、setInterval、I/O等)。

    1、setTimeout 定时器,属于js任务队列里的宏任务。 指的是把任务队列塞进执行栈里等待执行线程依次执行。虽然可以把它设置微0,但是仍然需要等待本轮执行环境里面的 所有同步和异步任务 执行完毕之后才会去执行它。

    2、promise es6的异步语法,属于js任务队列里的微任务。 在执行本轮宏任务的过程中,如果遇到promise,会将其塞入本轮执行过程的微任务,待本轮宏任务执行完毕之后,才会执行它。执行完毕之后,开始执行下一轮任务队列。

    题目二:

    async function async1() { console.log("async1 start"); await async2(); console.log("async1 end"); } async function async2() { console.log( 'async2'); } console.log("script start"); setTimeout(function () { console.log("settimeout"); },0); async1(); new Promise(function (resolve) { resolve(console.log("promise1")); }).then(function () { console.log("promise2"); }); console.log('script end');

    答案: script start async1 start async2 promise1 script end async1 end promise2 settimeout

    题目三:将promise调入前面,比较一下then和await

    new Promise(function (resolve) { resolve(console.log("promise1")); }).then(function () { console.log("promise2"); }); async function async1() { console.log("async1 start"); await async2(); console.log("async1 end"); } async function async2() { console.log( 'async2'); } console.log("script start"); setTimeout(function () { console.log("settimeout"); },0); async1(); console.log('script end');

    答案: script start async1 start async2 promise1 script end promise2 async1 end settimeout

    解析: 3、async await 异步语法,基于promise,是其语法糖,让异步更像同步任务。 如果使用async,函数体里有return XX,会被包装成一个异步promise.resolve(‘XXX’), 如果没有显式return,那么async也同样包装成promise.resolve(‘undefined’);

    注意:await 标志着js会去 先执行一遍后面紧跟的函数,然后马上让出线程,跳出整个async,去执行本轮执行周期里面的任务,等待本轮的宏任务(同步任务)执行完成之后,再回来async里等待之前await的函数的返回值,如果是返回值异步promise,那么会把它塞入promise.resolve()微任务(异步任务执行栈),等待它前面的异步任务执行完毕之后,再得到await promise.resolve()的值,然后才是去执行await后面的逻辑,如果await 函数体返回的不是异步promise,那么就直接去执行其后面的逻辑。

    😊终极大boss

    async function async1() { console.log("async1 start"); await async2(); const newPromise6 = new Promise(function(resolve, reject) { resolve(console.log('promise11111')); }).then(() => {console.log('then2222222')}); console.log("async1 end"); } async function async2() { console.log( 'async2'); } console.log("script start"); setTimeout(function () { console.log("settimeout"); },0); async1(); new Promise(function (resolve) { resolve(console.log("promise1")); }).then(function () { console.log("promise2"); }); console.log('script end');

    解析: 异步任务之间,会存在差异,所以它们执行的优先级也会有区别。 大致分为 微任务(microtask,如:Promise、MutaionObserver等)和 宏任务(macrotask,如:setTimeout、setInterval、I/O等)。

    答案: script start async1 start async2 promise1 script end promise11111 async1 end promise2 then2222222 settimeout

    作者:Danile_1226 原文链接:https://www.jianshu.com/p/80ed1ab7a95e

    setTimeout(function() { console.log(111) }, 0); setTimeout(function() { console.log(333) }, 1000); new Promise(function(resolve){ console.log(444); resolve(); console.log(555); }).then(function(){ console.log(666); }); console.log(777); async function test1() { console.log("test1"); await test2(); console.log("test1 last"); } async function test2() { console.log("test2"); } test1(); 输出结果: 444 555 777 test1 test2 666 test1 last 111 333

    理解:

    1、首先执行同步代码,然后以事件轮询的方式执行异步代码;

    2、promise中的异步体现在.then()和.catch()中,而promise中的function里的是同步代码;

    3、上面的代码是先执行promise里的同步代码,然后执行脚本里本身的代码;

    4、async无论方法是同步还是异步都可以用async关键字来进行标识;

    5、因为用async标识只是显示表明在该方法内,可能会用到awaitu关键字使其变为异步方法,而且将该异步方法进行了明确的划分,只有用了await关键字时才是异步操作,其余一并为同步操作;

    6、同generator函数一样,async函数返回一个promise对象,可以使用.then()方法添加回调函数;

    7、当函数执行的时候,一旦遇到await就先返回,等到触发的异步操作完成,再接着执行函数体内后面的语句;

    8、await命令后面的promise对象,运行结果可能是rejected,所以最好把await命令放在try……catch代码块中;

    原文链接:https://segmentfault.com/a/1190000017078299

    Processed: 0.017, SQL: 9