• <tbody id="9je1r"></tbody><tbody id="9je1r"><acronym id="9je1r"><rp id="9je1r"></rp></acronym></tbody>
      • <acronym id="9je1r"><acronym id="9je1r"><rp id="9je1r"></rp></acronym></acronym>

        亚洲无码Aⅴ,视频1页精品,欧美系列一区二区,曰韩色999

        js單線程中的同步和異步

        2020/11/16 14:33:22   閱讀:2656    發(fā)布者:2656


        單線程


        (1)單線程的概念

        JavaScript是一門單線程的語言,因此,JavaScript在同一個時間只能做一件事,單線程意味著,如果在同個時間有多個任務(wù)的話,這些任務(wù)就需要進(jìn)行排隊,前一個任務(wù)執(zhí)行完,才會執(zhí)行下一個任務(wù),比如說下面這段代碼
        // 同步代碼
        function fun1() {
        console.log(1);
        }
        function fun2() {
        console.log(2);
        }
        fun1();
        fun2();

        // 輸出
        1
        2

        很容易可以看出,輸出會依次輸入1,2,因為代碼是從上到下依次執(zhí)行,執(zhí)行完fun1(),才繼續(xù)執(zhí)行fun2(),但是如果fun1()中的代碼執(zhí)行的是讀取文件或者ajax操作,文件的讀取和數(shù)據(jù)的獲取都需要一定時間,難道我們需要完全等到fun1()執(zhí)行完才能繼續(xù)執(zhí)行fun2()么?為了解決這個問題,后面我們會介紹同步和異步的概念

        (2)為什么是單線程

        其實,JavaScript的單線程,與它的用途是有很大關(guān)系,我們都知道,JavaScript作為瀏覽器的腳本語言,主要用來實現(xiàn)與用戶的交互,利用JavaScript,我們可以實現(xiàn)對DOM的各種各樣的操作,如果JavaScript是多線程的話,一個線程在一個DOM節(jié)點中增加內(nèi)容,另一個線程要刪除這個DOM節(jié)點,那么這個DOM節(jié)點究竟是要增加內(nèi)容還是刪除呢?這會帶來很復(fù)雜的同步問題,因此,JavaScript是單線程的

        同步任務(wù)和異步任務(wù)



        (1)為什么會有同步和異步

        因為JavaScript的單線程,因此同個時間只能處理同個任務(wù),所有任務(wù)都需要排隊,前一個任務(wù)執(zhí)行完,才能繼續(xù)執(zhí)行下一個任務(wù),但是,如果前一個任務(wù)的執(zhí)行時間很長,比如文件的讀取操作或ajax操作,后一個任務(wù)就不得不等著,拿ajax來說,當(dāng)用戶向后臺獲取大量的數(shù)據(jù)時,不得不等到所有數(shù)據(jù)都獲取完畢才能進(jìn)行下一步操作,用戶只能在那里干等著,嚴(yán)重影響用戶體驗

        因此,JavaScript在設(shè)計的時候,就已經(jīng)考慮到這個問題,主線程可以完全不用等待文件的讀取完畢或ajax的加載成功,可以先掛起處于等待中的任務(wù),先運(yùn)行排在后面的任務(wù),等到文件的讀取或ajax有了結(jié)果后,再回過頭執(zhí)行掛起的任務(wù),因此,任務(wù)就可以分為同步任務(wù)和異步任務(wù)

        (2)同步任務(wù)

        同步任務(wù)是指在主線程上排隊執(zhí)行的任務(wù),只有前一個任務(wù)執(zhí)行完畢,才能繼續(xù)執(zhí)行下一個任務(wù),當(dāng)我們打開網(wǎng)站時,網(wǎng)站的渲染過程,比如元素的渲染,其實就是一個同步任務(wù)

        (3)異步任務(wù)

        異步任務(wù)是指不進(jìn)入主線程,而進(jìn)入任務(wù)隊列的任務(wù),只有任務(wù)隊列通知主線程,某個異步任務(wù)可以執(zhí)行了,該任務(wù)才會進(jìn)入主線程,當(dāng)我們打開網(wǎng)站時,像圖片的加載,音樂的加載,其實就是一個異步任務(wù)



        (4)異步機(jī)制

        那么,JavaScript中的異步是怎么實現(xiàn)的呢?那要需要說下回調(diào)和事件循環(huán)這兩個概念啦

        首先要先說下任務(wù)隊列,我們在前面也介紹了,異步任務(wù)是不會進(jìn)入主線程,而是會先進(jìn)入任務(wù)隊列,任務(wù)隊列其實是一個先進(jìn)先出的數(shù)據(jù)結(jié)構(gòu),也是一個事件隊列,比如說文件讀取操作,因為這是一個異步任務(wù),因此該任務(wù)會被添加到任務(wù)隊列中,等到IO完成后,就會在任務(wù)隊列中添加一個事件,表示異步任務(wù)完成啦,可以進(jìn)入執(zhí)行棧啦~但是這時候呀,主線程不一定有空,當(dāng)主線程處理完其它任務(wù)有空時,就會讀取任務(wù)隊列,讀取里面有哪些事件,排在前面的事件會被優(yōu)先進(jìn)行處理,如果該任務(wù)指定了回調(diào)函數(shù),那么主線程在處理該事件時,就會執(zhí)行回調(diào)函數(shù)中的代碼,也就是執(zhí)行異步任務(wù)啦


        單線程從從任務(wù)隊列中讀取任務(wù)是不斷循環(huán)的,每次棧被清空后,都會在任務(wù)隊列中讀取新的任務(wù),如果沒有任務(wù),就會等到,直到有新的任務(wù),這就叫做任務(wù)循環(huán),因為每個任務(wù)都是由一個事件觸發(fā)的,因此也叫作


        事件循環(huán)


        異步運(yùn)行機(jī)制如下:

        (1)所有同步任務(wù)都在主線程上執(zhí)行,形成一個執(zhí)行棧(execution context stack)。
        (2)主線程之外,還存在一個"任務(wù)隊列"(task queue)。只要異步任務(wù)有了運(yùn)行結(jié)果,就在"任務(wù)隊列"之中放置一個事件。
        (3)一旦"執(zhí)行棧"中的所有同步任務(wù)執(zhí)行完畢,系統(tǒng)就會讀取"任務(wù)隊列",看看里面有哪些事件。那些對應(yīng)的異步任務(wù),于是結(jié)束等待狀態(tài),進(jìn)入執(zhí)行棧,開始執(zhí)行。
        (4)主線程不斷重復(fù)上面的第三步。

        只要主線程空了,就會去讀取"任務(wù)隊列",這就是JavaScript的運(yùn)行機(jī)制。這個過程會不斷重復(fù)。
        "任務(wù)隊列"是一個事件的隊列(也可以理解成消息的隊列),IO設(shè)備完成一項任務(wù),就在"任務(wù)隊列"中添加一個事件,表示相關(guān)的異步任務(wù)可以進(jìn)入"執(zhí)行棧"了。主線程讀取"任務(wù)隊列",就是讀取里面有哪些事件。
        "任務(wù)隊列"中的事件,除了IO設(shè)備的事件以外,還包括一些用戶產(chǎn)生的事件(比如鼠標(biāo)點擊、頁面滾動等等),比如$(selectot).click(function),這些都是相對耗時的操作。只要指定過這些事件的回調(diào)函數(shù),這些事件發(fā)生時就會進(jìn)入"任務(wù)隊列",等待主線程讀取。
        所謂"回調(diào)函數(shù)"(callback),就是那些會被主線程掛起來的代碼,前面說的點擊事件$(selectot).click(function)中的function就是一個回調(diào)函數(shù)。異步任務(wù)必須指定回調(diào)函數(shù),當(dāng)主線程開始執(zhí)行異步任務(wù),就是執(zhí)行對應(yīng)的回調(diào)函數(shù)。例如ajax的success,complete,error也都指定了各自的回調(diào)函數(shù),這些函數(shù)就會加入“任務(wù)隊列”中,等待執(zhí)行。



        亚洲无码Aⅴ,视频1页精品,欧美系列一区二区,曰韩色999
            • <tbody id="9je1r"></tbody><tbody id="9je1r"><acronym id="9je1r"><rp id="9je1r"></rp></acronym></tbody>
            • <acronym id="9je1r"><acronym id="9je1r"><rp id="9je1r"></rp></acronym></acronym>
              新兴县| 新巴尔虎左旗| 永丰县| 海原县| 永丰县| 临漳县| 宜黄县| 阿克苏市| 墨竹工卡县| 宁乡县| 钟山县| 正安县| 色达县| 自贡市| 英超| 象州县| 集安市| 新晃| 容城县| 莱州市| 报价| 鲁山县| 惠安县| 文化| 南平市| 新田县| 呼和浩特市| 碌曲县| 洛阳市| 鸡西市| 启东市| 申扎县| 建湖县| 连城县| 东乌珠穆沁旗| 长沙市| 武夷山市| 库车县| 房山区| 尼勒克县| 黔西县|