最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 关于Javascript的异步

    正文概述 掘金(raotao)   2020-11-29   304
    宏任务(task)setTimeout、setInterval、Ajax、I/OUI交互事件(比如DOM事件)

    ​ 浏览器为了能够使得JS内部task与DOM任务能够有序的执行,会在一个task执行结束后,在下一个 task 执行开始前,对页面进行重新渲染 ?**(task->渲染->task->...)** 鼠标点击会触发一个事件回调,需要执行一个宏任务,然后解析HTMl。

    微任务(Microtasks )Promise回调、async/await、process.nextTick(Node独有)MutaionObserver

    ​ 微任务通常来说,就是需要在当前 task 执行结束后立即执行的任务,比如对一系列动作做出反馈,或或者是需要异步的执行任务而又不需要分配一个新的 task,这样便可以减小一点性能的开销。

    ​ ?只要执行栈中没有其他的js代码正在执行且每个宏任务执行完,微任务队列会立即执行。如果在微任务执行期间微任务队列加入了新的微任务,会将新的微任务加入队列尾部,之后也会被执行。微任务包括了mutation mutation 的回调还有接下来的例子promise的回调。

    来看一段代码

        async function test1() {
            console.log('start test1');
            console.log(await test2());
            console.log('end test1');
        }
        async function test2() {
            console.log('test2');
            return 'return test2 value'
        }
        test1();
    
        console.log('start async');
    
        setTimeout(() => {
            console.log('setTimeout');
        }, 0);
    
        new Promise((resolve, reject) => {
            console.log('promise1');
            resolve();
        }).then(() => {
            console.log('promise2');
        });
    

    模拟执行上面的代码

    1)执行 test1 函数,输出‘statr test1’;

    2)执行 console.log(await test2());根据debug顺序来看,是先执行test2() 它是一个async函数,输出 'test2' ;因为函数 retrun 有值 ,因此返回的Promise对象也是有值的,该Promise是下面这样的 ;但是因为有 await 的缘故 随后 console.log("return test2 value") 进入 微任务队列

    3)await 之后的代码也 console.log('end test1') 也进入微任务队列中

    4)执行console.log('start async'); 输出 'start async'

    5)遇到 setTimeout(...) 进入宏任务队列

    6)执行new Promise (..); 执行console.log('promise1') 输出 'promise1' ;

    执行resolve(); 改变该Promise状态;

    .then()中的代码进入微任务队列

    7)现在调用栈空了 ,轮询开始,先轮询微任务队列,再轮询宏任务队列

    微任务队列宏任务队列
    console.log('promise2');console.log('end test1')console.log("return test2 value");setTimeout(...)

    8)执行顺序是先进先出

    9)轮询微任务队列 输出 ’return test2 value‘ 、’end test1‘ 、 ’promise2‘

    10)轮询宏任务队列 输出 ’setTimeout‘

     "start test1"
     "test2"
     "start async"
     "promise1"
     "return test2 value"
     "end test1"
     "promise2"
     "setTimeout"
    

    同样的代码,在函数test2中, return await 'return test2 value' 事情会变成什么样?

    async function test1() {
          console.log('start test1');
          console.log(await test2());
          console.log('end test1');
        }
        async function test2() {
          console.log('test2');
          return await 'return test2 value'
        }
        test1();
    
        console.log('start async');
    
        setTimeout(() => {
          console.log('setTimeout');
        }, 0);
    
        new Promise((resolve, reject) => {
          console.log('promise1');
          resolve();
        }).then(() => {
          console.log('promise2');
        });
    
    
    
    微任务队列宏任务队列
    console.log('promise2');setTimeout(...)

    再次模拟执行上面的代码

    1)执行 test1 函数,输出‘statr test1’;

    2)执行 console.log(await test2());执行 test2() 它是一个async函数,首先进入函数体输出 'test2' ;

    但是由于函数 retrun 跟了一个 await ,因此这个代码没有执行完,回到 console.log(await test2()) 中,又是一个 await 因此也没有执行完,这段挂起了,意味着它阻塞了后面的代码,所以此时它返回的这个Promise 是处于pending 状态的;

    相当于你在等你女朋友,你女朋友在等车 ,一切都还没有结果。

    3)await 之后的代码也会被挂起 console.log('end test1') 挂起

    4)执行console.log('start async'); 输出 'start async'

    5)遇到 setTimeout(...) 进入宏任务队列

    6)执行new Promise (..); 执行console.log('promise1') 输出 'promise1' ;

    执行resolve(); 改变该Promise状态;.then()中的代码进入微任务队列

    7)现在调用栈空了 ,轮询开始,先轮询微任务队列

    8)执行顺序是先进先出

    9)轮询微任务队列 输出 ’promise2‘

    10)除挂起的代码外,别的都执行了一遍,回到刚刚挂起的地方 retrun await 'return test2 value'

    11)'return test2 value' 作为 tese2()的返回值 成功返回了 ,现在console.log("return test2 value")是进入 Call stack,输出 return test2 value

    12)console.log('end test1'); 进入call stack 输出 end test1

    !11)和12)我无法确定是进入调用栈直接输出,还是进入微任务,然后再轮询后再输出,正常来说是进入微任务再轮询执行的,但是debug调试发现是直接输出的。

    13)轮询 微任务队列 没有任务,接着轮询宏任务队列,有任务,执行 console.log('setTimeout'); 输出 ’setTimeout‘

        start test1
        test2
        start async
        promise1
        promise2
        return test2 value
        end test1
        setTimeout
    

    来一张有趣的图 关于Javascript的异步 总结一下

    1、async修饰符:async修饰的函数,默认返回 new Promise对象的resolve内容(若被async修饰的函数无返回值,则最终无返回值)。如此调用 async修饰的函数,可以直接使用then获取resolve值,用catch获取reject值。

    2、async方法内部,当程序执行到await方法时,会阻塞await方法后面的程序,进入await方法内部并执行到return前,然后跳出该async方法,执行与该async方法并列的同步任务。

    3、await 后面若是 Promise 会暂停执行,直到Promise 返回结果才继续,若不是 Promise 会立刻返回


    起源地下载网 » 关于Javascript的异步

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元