欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

單線程JavaScript實(shí)現(xiàn)異步過程詳解

 更新時(shí)間:2020年05月19日 10:15:21   作者:沐浴點(diǎn)陽光  
這篇文章主要介紹了單線程JavaScript實(shí)現(xiàn)異步過程詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

前兩天硬著頭皮在部門內(nèi)部做了一次技術(shù)分享,主題如題。索性整理成文章留個(gè)紀(jì)念!

要了解異步實(shí)現(xiàn),首先我們得先了解:

同步 & 異步

同步:會(huì)逐行執(zhí)行代碼,會(huì)對(duì)后續(xù)代碼造成阻塞,直至代碼接收到預(yù)期的結(jié)果之后,才會(huì)繼續(xù)向下執(zhí)行任務(wù)。

異步:調(diào)用之后先不管結(jié)果,繼續(xù)向下執(zhí)行任務(wù)。

網(wǎng)上各種文章對(duì)同步和異步的解釋也不外如是,但是看文字總是有點(diǎn)晦澀難懂!我就生活化的來比擬一下這兩個(gè)概念吧!

就好比請(qǐng)人吃飯:

比如你要請(qǐng)兩個(gè)人吃飯,一個(gè)是巴菲特,由于他是舉世矚目股神想請(qǐng)他吃飯的人從這里排到了法國,你為表誠意,你會(huì)精心打扮自己,請(qǐng)他跟你吃頓特色菜...那么為了請(qǐng)他吃個(gè)烤腰子,你全程都在為些事費(fèi)心費(fèi)力,投入大量的精力!

所以,也就阻塞了你干別的事情,是的,這就是同步!

請(qǐng)人吃頓飯就這么難嗎?當(dāng)然,也沒有那么難!不信,你請(qǐng)我吃飯?jiān)囋嚕?/p>

如果你想請(qǐng)我吃飯,那你只需要打個(gè)電話通知我一聲:喂,今天晚上請(qǐng)你吃個(gè)海底撈?。∥遥汉冒?!然后你不要來接我,到了點(diǎn)我自己去了!期間,你該干嘛就去干嘛!

看,其他也很簡單嘛?瞧,這就是異步!

那么回到代碼層面:

同步代碼:(代碼片段1)

function someTime() {
  let s = Date.now();
  while(true) {
    if (Date.now() - s > 2000) {
      console.log(2)
      break;
    }
  }
}
console.log(1);
someTime();
console.log(3);
// 其打印順序:1 ...(2秒以后)... 2 3

異步代碼:(代碼片段2)

function someTime() {
  setTimeout(() => {
    console.log(2);
  }, 2000)
}

console.log(1);
someTime();
console.log(3);

// 其打印順序:1 3 ...(2秒以后)... 2

看看,同步代碼,當(dāng)執(zhí)行這種耗時(shí)操作時(shí),就會(huì)停在原地,一定要等待這時(shí)間過去之后才會(huì)執(zhí)行后面的代碼!而異步代碼,后面的執(zhí)行完全不受影響...

JavaScript單線程

眾所周知JavaScript是單線程的,所謂單線程是指程序執(zhí)行時(shí),所走的程序路徑按照連續(xù)順序排下來,前面的必須處理好,后面的才會(huì)執(zhí)行!這個(gè)解釋跟【同步】的解釋如出一轍!

如此看起來異步編程對(duì)于單線程而言似乎并非正統(tǒng),甚至有點(diǎn)矛盾。然而,通過剛才的例子,我們發(fā)現(xiàn),JavaScript是真的實(shí)現(xiàn)了異步編程的!為啥加了個(gè)setTimeout()不能不阻塞了呢?按單線程的執(zhí)行的話那如下代碼會(huì)是怎么樣的呢?

function timeOut() {
  setTimeout(() => {
    console.log('timeOut');
  }, 0)
}
function someTime() {
  let s = Date.now();
  while(true) {
    if (Date.now() - s > 2000) {
      console.log('some Time')
      break;
    }
  }
}
console.log(1);
timeOut();
someTime();
console.log(3);

如果是以單線程那種解釋來執(zhí)行的話,這個(gè)打印順序應(yīng)該是:1 - time Out - some Time - 3才對(duì)!然而,其真正的執(zhí)行結(jié)果卻是:1 - some Time - 3 - time Out

為什么?瀏覽器的多線程

JavaScript是腳本語言,它需要在一個(gè)宿主環(huán)境里才能運(yùn)行,顯然我們接觸較多的宿主環(huán)境就是--瀏覽器!雖說JavaScript是單線程的,然而瀏覽器卻不是!

如圖所求,JavaScript引擎線程稱為主線程,它負(fù)責(zé)解析JavaScript代碼;其他可以稱為輔助線程,這些輔助線程便是JavaScript實(shí)現(xiàn)異步的關(guān)鍵了!

如(代碼片段2):主線程負(fù)責(zé)自上而下順序執(zhí)行,當(dāng)遇到setTimeout函數(shù)后,便將其交給定時(shí)器線程去執(zhí)行,自己繼續(xù)執(zhí)行下面的代碼!從而達(dá)到異步的目的。

不僅如此,更關(guān)鍵的是:

任務(wù)隊(duì)列

當(dāng)定時(shí)器線程計(jì)時(shí)執(zhí)行完之后,會(huì)將回調(diào)函數(shù)放入任務(wù)隊(duì)列中!

當(dāng)這些任務(wù)加入到任務(wù)隊(duì)列后并不會(huì)立即執(zhí)行,而是處于等候狀態(tài)!等主線程處理完了自己的事情后,才來執(zhí)行任務(wù)隊(duì)列中任務(wù)!

這個(gè)過程我感覺像是古代嬪妃被翻了牌子后,就需要在自己寢宮里精心準(zhǔn)備,等待皇上批完湊折后的駕臨...(哦,別想歪了!)

宏任務(wù) & 微任務(wù)

然而,異步任務(wù)卻又分為兩種:一種叫“宏任務(wù)”(MacroTask 或者 Task),一種叫“微任務(wù)”(MicroTask)!

這又是兩個(gè)啥玩意呢?

光看這個(gè)依然晦澀難懂,那我們來看一段代碼吧!

console.log(1);
setTimeout(() => {
  console.log(2);
}, 0);
Promise.resolve().then(() => {
  console.log(3);
});
console.log(4);

這段代碼的執(zhí)行結(jié)果:1 - 4 - 3 - 2。LOOK!2是最后打印的,哪怕該計(jì)時(shí)器的時(shí)間設(shè)置為0。通過之前的同步和異步的解釋,1和4先于2打印應(yīng)該很好理解了,但同樣是異步,3也優(yōu)先于2打印,這又是為什么呢?答案就是因?yàn)?setTimeout屬于宏任務(wù),而Promise屬于微任務(wù)!

好吧~ 這就是宏任務(wù)和微任務(wù)的差別...什么?沒懂?

微任務(wù)是皇后所生的,是嫡子;而宏任務(wù)是某個(gè)小妃子所生, 是庶子!你說選太子的時(shí)候誰優(yōu)先?

瀏覽器的Event Loop

1.執(zhí)行全局Script同步代碼,形成一個(gè)執(zhí)行棧;

2.在執(zhí)行代碼時(shí)當(dāng)遇到如上異步任務(wù)時(shí)便會(huì)按上文所描述的將宏任務(wù)回調(diào)加入宏任務(wù)隊(duì)列,微任務(wù)回調(diào)加入微任務(wù)隊(duì)列;

3.然而,回調(diào)函數(shù)放入任務(wù)隊(duì)列后也不是立即執(zhí)行;會(huì)等待執(zhí)行棧中的同步任務(wù)全部執(zhí)行完清空了棧后引擎才能會(huì)去任務(wù)隊(duì)列檢查是否有任務(wù),如果有那便會(huì)將這些任務(wù)加入執(zhí)行棧,然后執(zhí)行!

4.執(zhí)行棧清空后,會(huì)先去檢查微任務(wù)隊(duì)列是否有任務(wù),逐一將其任務(wù)加入執(zhí)行棧中執(zhí)行,期間如果又產(chǎn)生了微任務(wù)那繼續(xù)將其加入到列隊(duì)末尾,并在本周期內(nèi)執(zhí)行完,直到微任務(wù)隊(duì)列的任務(wù)全部 清空,執(zhí)行棧也清空后,再去檢查宏任務(wù)隊(duì)列是否有任務(wù),取到隊(duì)列隊(duì)頭的任務(wù)放入到執(zhí)行棧中執(zhí)行,其他可能又會(huì)產(chǎn)生微任務(wù),那當(dāng)本次執(zhí)行棧中的任務(wù)結(jié)果清空后又會(huì)去檢查微任務(wù)隊(duì)列...

5.引擎會(huì)循環(huán)執(zhí)行如上步驟,這就是Event Loop!

又要上代碼了:

console.log('start');
setTimeout(() => {
  console.log('time1');
  Pormise.resolve().then(() => {
    console.log('promise1');
  })
}, 0);
setTimeout(() => {
  console.log('time2');
  Pormise.resolve().then(() => {
    console.log('promise2');
  })
}, 0);
Pormise.resolve().then(() => {
  console.log('promise3');
});
console.log('end');

這段代碼的打印順序:

start - end - promise3 - timer1 - promise1 - timer2 - promise2

據(jù)說:node 10.x版本上面的輸入結(jié)果會(huì)是:

start - end - promise3 - timer1 - timer2 - promise1 - promise2

node 11.x版本以后改了,輸出跟瀏覽器輸出一致了!

Web Worker

HTML5中支持了Web Worker,使得能夠同時(shí)執(zhí)行兩段JS了,那是不是就是說JS實(shí)現(xiàn)了“多線程”了呢?我們來看看Web Worker的官方解釋:

通過使用Web Workers,Web應(yīng)用程序可以在獨(dú)立于主線程的后臺(tái)線程中,運(yùn)行一個(gè)腳本操作。這樣做的好處是可以在獨(dú)立線程中執(zhí)行費(fèi)時(shí)的處理任務(wù),從而允許主線程(通常是UI線程)不會(huì)因此被阻塞/放慢。

獨(dú)立線程,看似像是實(shí)現(xiàn)了“多線程”,然而他是獨(dú)立于主線程,也就是主線程依然是那個(gè)主線程沒有變!雖然你大媽已經(jīng)不是你大媽了,但是你大爺還是你大爺!JS單線程的本質(zhì)依然沒有變!

WebWorker是向?yàn)g覽器申請(qǐng)一個(gè)子線程,該子線程服務(wù)于主線程,完全受主線程控制。

Web Worker注意事項(xiàng):

寫了一個(gè)demo:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Web Worker</title>
</head>
<body>
  <button onclick="startWorker()">開始</button>
  <button onclick="stopWorker()">停止</button>
  <button onclick="updateNum()">在運(yùn)行時(shí)點(diǎn)擊</button>
  <div id="output"></div>
  <div id="num"></div>

  <script id="worker" type="app/worker">
    function updateSync() {
      for (let i = 0; i < 10000000000; i++) {
        if (i % 100000 === 0) {
          postMessage(i);
        }
      }
    }
    updateSync();
  </script>

  <script>
    let worker;
    function startWorker() {
      let blob = new Blob([document.querySelector('#worker').textContent]);
      let url = window.URL.createObjectURL(blob);
      console.log(url);
      worker = new Worker(url);

      worker.onmessage = function(e) {
        document.getElementById('output').innerHTML = e.data;
      }
    }

    function stopWorker() {
      if (worker) {
        worker.terminate();
      }
    }
    
    let num = 0;
    function updateNum() {
      num++;
      document.getElementById('num').innerHTML = num;
    }
  </script>
</body>
</html>

這段代碼可以稍微解釋一下Web Worker的用途之一 --執(zhí)行費(fèi)時(shí)的處理任務(wù)吧!

以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 深入理解javascript中concat方法

    深入理解javascript中concat方法

    本文主要介紹了javascript中concat方法,主要分為2小節(jié)內(nèi)容:1.concat方法的基礎(chǔ)介紹;2.從實(shí)例中感受concat方法。需要的朋友一起來看下吧
    2016-12-12
  • JavaScript之ECharts用法講解

    JavaScript之ECharts用法講解

    這篇文章主要介紹了JavaScript之ECharts用法講解,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • js動(dòng)態(tài)生成form 并用ajax方式提交的實(shí)現(xiàn)方法

    js動(dòng)態(tài)生成form 并用ajax方式提交的實(shí)現(xiàn)方法

    下面小編就為大家?guī)硪黄猨s動(dòng)態(tài)生成form 并用ajax方式提交的實(shí)現(xiàn)方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-09-09
  • 微信小程序網(wǎng)絡(luò)封裝(簡單高效)

    微信小程序網(wǎng)絡(luò)封裝(簡單高效)

    這篇文章主要介紹了微信小程序網(wǎng)絡(luò)封裝(簡單高效),微信小程序的網(wǎng)絡(luò)請(qǐng)求很便捷,直接調(diào)用就可以了。小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-08-08
  • 我也種棵OO樹JXTree[js+css+xml]

    我也種棵OO樹JXTree[js+css+xml]

    我也種棵OO樹JXTree[js+css+xml]...
    2007-04-04
  • 基于JavaScript實(shí)現(xiàn)文件秒傳功能

    基于JavaScript實(shí)現(xiàn)文件秒傳功能

    在互聯(lián)網(wǎng)高速發(fā)展的今天,文件上傳已經(jīng)成為網(wǎng)頁應(yīng)用中的一個(gè)基本功能,隨著用戶上傳文件尺寸的不斷增大、對(duì)質(zhì)量清晰度的要求也越來越高,所以本文給大家介紹了如何使用JavaScript實(shí)現(xiàn)文件秒傳功能,需要的朋友可以參考下
    2024-01-01
  • 獲取表單控件原始(初始)值的方法

    獲取表單控件原始(初始)值的方法

    獲取表單控件原始值在某些時(shí)候還是比較實(shí)用的,具體的獲取方法如下,感興趣的朋友可以參考下,希望對(duì)大家有所幫助
    2013-08-08
  • 微信小程序淘寶首頁雙排圖片布局排版代碼(推薦)

    微信小程序淘寶首頁雙排圖片布局排版代碼(推薦)

    這篇文章主要介紹了微信小程序淘寶首頁雙排圖片布局排版代碼,本文通過圖文實(shí)例相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-10-10
  • JavaScript數(shù)組操作詳解

    JavaScript數(shù)組操作詳解

    本文主要介紹了JavaScript的數(shù)組操作,具有很好的參考價(jià)值,下面跟著小編一起來看下吧
    2017-02-02
  • 微信小程序整合使用富文本編輯器的方法詳解

    微信小程序整合使用富文本編輯器的方法詳解

    這篇文章主要介紹了微信小程序整合使用富文本編輯器的方法,結(jié)合實(shí)例形式分析了微信小程序整合與使用富文本插件WxParse相關(guān)步驟與操作技巧,需要的朋友可以參考下
    2019-04-04

最新評(píng)論