成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

細(xì)說JavaScript單線程的一些事

coolpail / 2889人閱讀

摘要:標(biāo)簽單線程首發(fā)地址碼農(nóng)網(wǎng)細(xì)說單線程的一些事最近被同學(xué)問道單線程的一些事,我竟回答不上。若以多線程的方式操作這些,則可能出現(xiàn)操作的沖突。另外,因?yàn)槭菃尉€程的,在某一時(shí)刻內(nèi)只能執(zhí)行特定的一個(gè)任務(wù),并且會阻塞其它任務(wù)執(zhí)行。

標(biāo)簽: JavaScript 單線程


首發(fā)地址:碼農(nóng)網(wǎng)《細(xì)說JavaScript單線程的一些事》

最近被同學(xué)問道 JavaScript 單線程的一些事,我竟回答不上。好吧,感覺自己的 JavaScript 白學(xué)了。下面是我這幾天整理的一些關(guān)于 JavaScript 單線程的一些事。

首先,說下為什么 JavaScript 是單線程?

總所周知,JavaScript 是以單線程的方式運(yùn)行的。說到線程就自然聯(lián)想到進(jìn)程。那它們有什么聯(lián)系呢?

進(jìn)程和線程都是操作系統(tǒng)的概念。進(jìn)程是應(yīng)用程序的執(zhí)行實(shí)例,每一個(gè)進(jìn)程都是由私有的虛擬地址空間、代碼、數(shù)據(jù)和其它系統(tǒng)資源所組成;進(jìn)程在運(yùn)行過程中能夠申請創(chuàng)建和使用系統(tǒng)資源(如獨(dú)立的內(nèi)存區(qū)域等),這些資源也會隨著進(jìn)程的終止而被銷毀。而線程則是進(jìn)程內(nèi)的一個(gè)獨(dú)立執(zhí)行單元,在不同的線程之間是可以共享進(jìn)程資源的,所以在多線程的情況下,需要特別注意對臨界資源的訪問控制。在系統(tǒng)創(chuàng)建進(jìn)程之后就開始啟動執(zhí)行進(jìn)程的主線程,而進(jìn)程的生命周期和這個(gè)主線程的生命周期一致,主線程的退出也就意味著進(jìn)程的終止和銷毀。主線程是由系統(tǒng)進(jìn)程所創(chuàng)建的,同時(shí)用戶也可以自主創(chuàng)建其它線程,這一系列的線程都會并發(fā)地運(yùn)行于同一個(gè)進(jìn)程中。

顯然,在多線程操作下可以實(shí)現(xiàn)應(yīng)用的并行處理,從而以更高的 CPU 利用率提高整個(gè)應(yīng)用程序的性能和吞吐量。特別是現(xiàn)在很多語言都支持多核并行處理技術(shù),然而 JavaScript 卻以單線程執(zhí)行,為什么呢?

其實(shí)這與它的用途有關(guān)。作為瀏覽器腳本語言,JavaScript 的主要用途是與用戶互動,以及操作 DOM。若以多線程的方式操作這些 DOM,則可能出現(xiàn)操作的沖突。假設(shè)有兩個(gè)線程同時(shí)操作一個(gè) DOM 元素,線程 1 要求瀏覽器刪除 DOM,而線程 2 卻要求修改 DOM 樣式,這時(shí)瀏覽器就無法決定采用哪個(gè)線程的操作。當(dāng)然,我們可以為瀏覽器引入“鎖”的機(jī)制來解決這些沖突,但這會大大提高復(fù)雜性,所以 JavaScript 從誕生開始就選擇了單線程執(zhí)行。

另外,因?yàn)?JavaScript 是單線程的,在某一時(shí)刻內(nèi)只能執(zhí)行特定的一個(gè)任務(wù),并且會阻塞其它任務(wù)執(zhí)行。那么對于類似 I/O 等耗時(shí)的任務(wù),就沒必要等待他們執(zhí)行完后才繼續(xù)后面的操作。在這些任務(wù)完成前,JavaScript 完全可以往下執(zhí)行其他操作,當(dāng)這些耗時(shí)的任務(wù)完成后則以回調(diào)的方式執(zhí)行相應(yīng)處理。這些就是 JavaScript 與生俱來的特性:異步與回調(diào)。

當(dāng)然對于不可避免的耗時(shí)操作(如:繁重的運(yùn)算,多重循環(huán)),HTML5 提出了Web Worker,它會在當(dāng)前 JavaScript 的執(zhí)行主線程中利用 Worker 類新開辟一個(gè)額外的線程來加載和運(yùn)行特定的 JavaScript 文件,這個(gè)新的線程和 JavaScript 的主線程之間并不會互相影響和阻塞執(zhí)行,而且在 Web Worker 中提供了這個(gè)新線程和 JavaScript 主線程之間數(shù)據(jù)交換的接口:postMessage 和 onMessage 事件。但在 HTML5 Web Worker 中是不能操作 DOM 的,任何需要操作 DOM 的任務(wù)都需要委托給 JavaScript 主線程來執(zhí)行,所以雖然引入 HTML5 Web Worker,但仍然沒有改線 JavaScript 單線程的本質(zhì)。

并發(fā)模式與 Event Loop

JavaScript 有個(gè)基于“Event Loop”并發(fā)的模型。
啊,并發(fā)?不是說 JavaScript 是單線程嗎? 沒錯,的確是單線程,但是并發(fā)與并行是有區(qū)別的。
前者是邏輯上的同時(shí)發(fā)生,而后者是物理上的同時(shí)發(fā)生。所以,單核處理器也能實(shí)現(xiàn)并發(fā)。



并發(fā)與并行

并行大家都好理解,而所謂“并發(fā)”是指兩個(gè)或兩個(gè)以上的事件在同一時(shí)間間隔中發(fā)生。如上圖的第一個(gè)表,由于計(jì)算機(jī)系統(tǒng)只有一個(gè) CPU,故 ABC 三個(gè)程序從“微觀”上是交替使用 CPU,但交替時(shí)間很短,用戶察覺不到,形成了“宏觀”意義上的并發(fā)操作。

Runtime 概念

下面的內(nèi)容解釋一個(gè)理論上的模型?,F(xiàn)代 JavaScript 引擎已著重實(shí)現(xiàn)和優(yōu)化了以下所描述的幾個(gè)概念。

Stack(棧)

這里放著 JavaScript 正在執(zhí)行的任務(wù)。每個(gè)任務(wù)被稱為幀(stack of frames)。

function f(b) {
  var a = 12;
  return a + b + 35;
}

function g(x) {
  var m = 4;
  return f(m * x);
}

g(21);

上述代碼調(diào)用 g 時(shí),創(chuàng)建棧的第一幀,該幀包含了 g 的參數(shù)和局部變量。當(dāng) g 調(diào)用 f 時(shí),第二幀就會被創(chuàng)建,并且置于第一幀之上,當(dāng)然,該幀也包含了 f 的參數(shù)和局部變量。當(dāng) f 返回時(shí),其對應(yīng)的幀就會出棧。同理,當(dāng) g 返回時(shí),棧就為空了(棧的特定就是后進(jìn)先出 Last-in first-out (LIFO))。

Heap(堆)

一個(gè)用來表示內(nèi)存中一大片非結(jié)構(gòu)化區(qū)域的名字,對象都被分配在這。

Queue(隊(duì)列)

一個(gè) JavaScript runtime 包含了一個(gè)任務(wù)隊(duì)列,該隊(duì)列是由一系列待處理的任務(wù)組成。而每個(gè)任務(wù)都有相對應(yīng)的函數(shù)。當(dāng)棧為空時(shí),就會從任務(wù)隊(duì)列中取出一個(gè)任務(wù),并處理之。該處理會調(diào)用與該任務(wù)相關(guān)聯(lián)的一系列函數(shù)(因此會創(chuàng)建一個(gè)初始棧幀)。當(dāng)該任務(wù)處理完畢后,棧就會再次為空。(Queue的特點(diǎn)是先進(jìn)先出 First-in First-out (FIFO))。

為了方便描述與理解,作出以下約定:

Stack 棧為主線程

Queue 隊(duì)列為任務(wù)隊(duì)列(等待調(diào)度到主線程執(zhí)行)

OK,上述知識點(diǎn)幫助我們理清了一個(gè) JavaScript runtime 的相關(guān)概念,這有助于接下來的分析。

Event Loop

之所以被稱為 Event loop,是因?yàn)樗砸韵骂愃品绞綄?shí)現(xiàn):

while(queue.waitForMessage()) {
  queue.processNextMessage();
}

正如上述所說,“任務(wù)隊(duì)列”是一個(gè)事件的隊(duì)列,如果 I/O 設(shè)備完成任務(wù)或用戶觸發(fā)事件(該事件指定了回調(diào)函數(shù)),那么相關(guān)事件處理函數(shù)就會進(jìn)入“任務(wù)隊(duì)列”,當(dāng)主線程空閑時(shí),就會調(diào)度“任務(wù)隊(duì)列”里第一個(gè)待處理任務(wù)(FIFO)。當(dāng)然,對于定時(shí)器,當(dāng)?shù)竭_(dá)其指定時(shí)間時(shí),才會把相應(yīng)任務(wù)插到“任務(wù)隊(duì)列”尾部。

“執(zhí)行至完成”

每當(dāng)某個(gè)任務(wù)執(zhí)行完后,其它任務(wù)才會被執(zhí)行。也就是說,當(dāng)一個(gè)函數(shù)運(yùn)行時(shí),它不能被取代且會在其它代碼運(yùn)行前先完成。
當(dāng)然,這也是 Event Loop 的一個(gè)缺點(diǎn):當(dāng)一個(gè)任務(wù)完成時(shí)間過長,那么應(yīng)用就不能及時(shí)處理用戶的交互(如點(diǎn)擊事件),甚至導(dǎo)致該應(yīng)用奔潰。一個(gè)比較好解決方案是:將任務(wù)完成時(shí)間縮短,或者盡可能將一個(gè)任務(wù)分成多個(gè)任務(wù)執(zhí)行。

絕不阻塞

JavaScript 與其它語言不同,其 Event Loop 的一個(gè)特性是永不阻塞。I/O 操作通常是通過事件和回調(diào)函數(shù)處理。所以,當(dāng)應(yīng)用等待 indexedDB 或 XHR 異步請求返回時(shí),其仍能處理其它操作(如用戶輸入)。

例外是存在的,如 alert 或者同步 XHR,但避免它們被認(rèn)為是最佳實(shí)踐。注意的是,例外的例外也是存在的(但通常是實(shí)現(xiàn)錯誤而非其它原因)。

定時(shí)器 定時(shí)器的一些概念

上面也提到,在到達(dá)指定時(shí)間時(shí),定時(shí)器就會將相應(yīng)回調(diào)函數(shù)插入“任務(wù)隊(duì)列”尾部。這就是“定時(shí)器(timer)”功能。

定時(shí)器 包括 setTimeout 與 setInterval 兩個(gè)方法。它們的第二個(gè)參數(shù)是指定其回調(diào)函數(shù)推遲每隔多少毫秒數(shù)后執(zhí)行。

對于第二個(gè)參數(shù)有以下需要注意的地方:

當(dāng)?shù)诙€(gè)參數(shù)缺省時(shí),默認(rèn)為 0;

當(dāng)指定的值小于 4 毫秒,則增加到 4ms(4ms 是 HTML5 標(biāo)準(zhǔn)指定的,對于 2010 年及之前的瀏覽器則是 10ms);

如果你理解上述知識,那么以下代碼就應(yīng)該對你沒什么問題了:

console.log(1);
setTimeout(function() {
  console.log(2);
},10);
console.log(3);
// 輸出:1 3 2
深入了解定時(shí)器
零延遲 setTimeout(func, 0)

零延遲并不是意味著回調(diào)函數(shù)立刻執(zhí)行。它取決于主線程當(dāng)前是否空閑與“任務(wù)隊(duì)列”里其前面正在等待的任務(wù)。

看看以下代碼:

(function () {

  console.log("this is the start");

  setTimeout(function cb() {
    console.log("this is a msg from callback");
  });

  console.log("this is just a message");

  setTimeout(function cb1() {
    console.log("this is a msg from callback1");
  }, 0);

  console.log("this is the end");

})();

// 輸出如下:
this is the start
this is just a message
this is the end
undefined // 立即調(diào)用函數(shù)的返回值
this is a msg from callback
this is a msg from callback1
setTimeout(func, 0) 的作用

讓瀏覽器渲染當(dāng)前的元素更改(瀏覽器將 UI render 和 JavaScript 的執(zhí)行是放在一個(gè)線程中,線程阻塞會導(dǎo)致界面無法更新渲染)

重新評估“scriptis running too long”警告

改變執(zhí)行順序

再看看以下代碼:


$("#do").on("click", function() { // 此處會觸發(fā) redraw 事件,但會放到隊(duì)列里執(zhí)行,直到 long() 執(zhí)行完。 $("#status").text("calculating...."); // 沒設(shè)定定時(shí)器,用戶將無法看到 “calculating...” // 這是因?yàn)椤癱alculation”的 redraw 事件會緊接在 // “calculating...”的 redraw 事件后執(zhí)行 long(); // 執(zhí)行長時(shí)間任務(wù),造成阻塞 // 設(shè)定了定時(shí)器,用戶就如期看到“calculating...” // 大約 50ms 后,將耗時(shí)長的 long 回調(diào)函數(shù)插入“任務(wù)隊(duì)列”末尾, // 根據(jù)先進(jìn)先出原則,其將在 redraw 之后被調(diào)度到主線程執(zhí)行 //setTimeout(long,50); }); function long() { var result = 0; for (var i = 0; i<1000; i++){ for (var j = 0; j<1000; j++){ for (var k = 0; k<1000; k++){ result = result + i+j+k; } } } // 在本案例中,該語句必須放到這里,這將使它與回調(diào)函數(shù)的行為類似 $("#status").text("calculation done"); }
正版與翻版 setInterval 的區(qū)別

大家都可能知道通過 setTimeout 可以模仿 setInterval 的效果,下面我們看看以下代碼的區(qū)別:

// 利用 setTimeout 模仿 setInterval
setTimeout(function() {
  /* 執(zhí)行一些操作. */
  setTimeout(arguments.callee, 1000);
}, 1000);

setInterval(function() {
  /* 執(zhí)行一些操作 */
}, 1000);

可能你認(rèn)為這沒什么區(qū)別。的確,當(dāng)回調(diào)函數(shù)里的操作耗時(shí)很短時(shí),并不能看出它們有什么區(qū)別。
其實(shí):上面案例中的 setTimeout 總是會在其回調(diào)函數(shù)執(zhí)行后延遲 1000ms(或者更多,但不可能少)再次執(zhí)行回調(diào)函數(shù),從而實(shí)現(xiàn) setInterval 的效果,而 setInterval 總是 1000ms 執(zhí)行一次,而不管它的回調(diào)函數(shù)執(zhí)行多久。

所以,如果 setInterval 的回調(diào)函數(shù)執(zhí)行時(shí)間比你指定的間隔時(shí)間相等或者更長,那么其回調(diào)函數(shù)會連在一起執(zhí)行。

你可以試試運(yùn)行以下代碼:

var counter = 0;
  var initTime = new Date().getTime();
  var timer = setInterval(function() {
    if(counter===2) {
      clearInterval(timer);
    }
    if(counter === 0) {
      for(var i = 0; i < 1990000000; i++) {
        ;
      }
    }

    console.log("第"+counter+"次:" + (new Date().getTime() - initTime) + " ms");

    counter++;
},1000);

我電腦 Chrome 瀏覽器的輸入如下:

第0次:2007 ms
第1次:2013 ms
第2次:3008 ms

從上面的執(zhí)行結(jié)果可看出,第一次和第二次執(zhí)行間隔很短(不足 1000ms)。

瀏覽器 瀏覽器不是單線程的

上面說了這么多關(guān)于 JavaScript 是單線程的,下面說說其宿主環(huán)境——瀏覽器。
瀏覽器的內(nèi)核是多線程的,它們在內(nèi)核制控下相互配合以保持同步,一個(gè)瀏覽器至少實(shí)現(xiàn)三個(gè)常駐線程:

JavaScript 引擎線程 JavaScript 引擎是基于事件驅(qū)動單線程執(zhí)行的,JavaScript 引擎一直等待著任務(wù)隊(duì)列中任務(wù)的到來,然后加以處理。

GUI 渲染線程 GUI 渲染線程負(fù)責(zé)渲染瀏覽器界面,當(dāng)界面需要重繪(Repaint)或由于某種操作引發(fā)回流(reflow)時(shí),該線程就會執(zhí)行。但需要注意 GUI 渲染線程與 JavaScript 引擎是互斥的,當(dāng) JavaScript 引擎執(zhí)行時(shí) GUI 線程會被掛起,GUI 更新會被保存在一個(gè)隊(duì)列中等到 JavaScript 引擎空閑時(shí)立即被執(zhí)行。

瀏覽器事件觸發(fā)線程事件觸發(fā)線程,當(dāng)一個(gè)事件被觸發(fā)時(shí)該線程會把事件添加到“任務(wù)隊(duì)列”的隊(duì)尾,等待 JavaScript 引擎的處理。這些事件可來自 JavaScript 引擎當(dāng)前執(zhí)行的代碼塊如 setTimeOut、也可來自瀏覽器內(nèi)核的其他線程如鼠標(biāo)點(diǎn)擊、AJAX 異步請求等,但由于 JavaScript 是單線程執(zhí)行的,所有這些事件都得排隊(duì)等待 JavaScript 引擎處理。

在 Chrome 瀏覽器中,為了防止因一個(gè)標(biāo)簽頁奔潰而影響整個(gè)瀏覽器,其每個(gè)標(biāo)簽頁都是一個(gè)進(jìn)程(Renderer Process)。當(dāng)然,對于同一域名下的標(biāo)簽頁是能夠相互通訊的,具體可看 瀏覽器跨標(biāo)簽通訊。在 Chrome 設(shè)計(jì)中存在很多的進(jìn)程,并利用進(jìn)程間通訊來完成它們之間的同步,因此這也是 Chrome 快速的法寶之一。對于 Ajax 的請求也需要特殊線程來執(zhí)行,當(dāng)需要發(fā)送一個(gè) Ajax 請求時(shí),瀏覽器會開辟一個(gè)新的線程來執(zhí)行 HTTP 的請求,它并不會阻塞 JavaScript 線程的執(zhí)行,當(dāng) HTTP 請求狀態(tài)變更時(shí),相應(yīng)事件會被作為回調(diào)放入到“任務(wù)隊(duì)列”中等待被執(zhí)行。

看看以下代碼:

document.onclick = function() {
  console.log("click");
}

for(var i = 0; i< 100000000; i++);

解釋一下代碼:首先向 document 注冊了一個(gè) click 事件,然后就執(zhí)行了一段耗時(shí)的 for 循環(huán),在這段 for 循環(huán)結(jié)束前,你可以嘗試點(diǎn)擊頁面。當(dāng)耗時(shí)操作結(jié)束后,console 控制臺就會輸出之前點(diǎn)擊事件的“click”語句。這證明了點(diǎn)擊事件(也包括其它各種事件)是由額外多帶帶的線程觸發(fā)的,事件觸發(fā)后就會將回調(diào)函數(shù)放進(jìn)了“任務(wù)隊(duì)列”的末尾,等待著 JavaScript 主線程的執(zhí)行。

總結(jié)

JavaScript 是單線程的,同一時(shí)刻只能執(zhí)行特定的任務(wù),而瀏覽器是多線程的。

異步任務(wù)(各種瀏覽器事件、定時(shí)器等)都是先添加到“任務(wù)隊(duì)列”(定時(shí)器則到達(dá)其指定參數(shù)時(shí))。當(dāng) Stack 棧(JavaScript 主線程)為空時(shí),就會讀取 Queue 隊(duì)列(任務(wù)隊(duì)列)的第一個(gè)任務(wù)(隊(duì)首),然后執(zhí)行。

JavaScript 為了避免復(fù)雜性,而實(shí)現(xiàn)單線程執(zhí)行。而如今 JavaScript 卻變得越來越不簡單了,當(dāng)然這也是 JavaScript 迷人的地方。

后續(xù)更新(回復(fù)網(wǎng)友的問題)

關(guān)于"setTimeout(func, 0)的作用"一節(jié)中,redraw事件發(fā)生后,事件處理函數(shù)被插入任務(wù)隊(duì)列,等待當(dāng)前棧中l(wèi)ong函數(shù)執(zhí)行完畢再執(zhí)行。此時(shí)通過setTimeout(long,0)即可將long函數(shù)插到任務(wù)隊(duì)列中redraw事件處理函數(shù)的后面。事實(shí)上Chrome中也確實(shí)是這么處理的(我的版本號是55.0.2883.87 m),可是最新的火狐和Edge都至少要將延時(shí)設(shè)置為15ms以上,請問這是為什么?

答:恩,這的確取決于瀏覽器的內(nèi)部實(shí)現(xiàn)。

昨晚,我看了Chrome(chromium)的定時(shí)器源碼實(shí)現(xiàn):

一些變量的定義:

static const int maxIntervalForUserGestureForwarding = 1000; // One second matches Gecko.
static const int maxTimerNestingLevel = 5;
static const double oneMillisecond = 0.001;
// Chromium uses a minimum timer interval of 4ms. We"d like to go
// lower; however, there are poorly coded websites out there which do
// create CPU-spinning loops.  Using 4ms prevents the CPU from
// spinning too busily and provides a balance between CPU spinning and
// the smallest possible interval timer.
static const double minimumInterval = 0.004;

定時(shí)器的部分實(shí)現(xiàn):

DOMTimer::DOMTimer(ExecutionContext* context, ScheduledAction* action, int interval, bool singleShot, int timeoutID)
    : SuspendableTimer(context)
    , m_timeoutID(timeoutID)
    , m_nestingLevel(context->timers()->timerNestingLevel() + 1)
    , m_action(action)
{
    ASSERT(timeoutID > 0);
    if (shouldForwardUserGesture(interval, m_nestingLevel))
        m_userGestureToken = UserGestureIndicator::currentToken();

    InspectorInstrumentation::asyncTaskScheduled(context, singleShot ? "setTimeout" : "setInterval", this, !singleShot);

    double intervalMilliseconds = std::max(oneMillisecond, interval * oneMillisecond);
    if (intervalMilliseconds < minimumInterval && m_nestingLevel >= maxTimerNestingLevel)
        intervalMilliseconds = minimumInterval;
    if (singleShot)
        startOneShot(intervalMilliseconds, BLINK_FROM_HERE);
    else
        startRepeating(intervalMilliseconds, BLINK_FROM_HERE);
}

從上述代碼可看出:Chrome 實(shí)現(xiàn)的定時(shí)器的最小時(shí)間間隔是 1ms。只有滿足 intervalMilliseconds < minimumInterval && m_nestingLevel >= maxTimerNestingLevel 該條件時(shí),定時(shí)器的最小時(shí)間間隔才是 4ms。

因此,各瀏覽器是往響應(yīng)更快的方向發(fā)展的。


對于你提問的“在Edge和火狐上,redraw事件和setTimeout執(zhí)行順序問題”,也同樣取決于瀏覽器的內(nèi)部實(shí)現(xiàn)。

我在我電腦的Edge和火狐瀏覽器上進(jìn)行測試,當(dāng)時(shí)間間隔較小時(shí)(如 0~10ms),redraw和setTimeout的執(zhí)行順序是不固定的。

因此,這需要你經(jīng)過足夠多的測試,得到一個(gè)相對安全的時(shí)間值,以確保執(zhí)行順序的正確性。

參考資料:

JavaScript 運(yùn)行機(jī)制詳解:再談Event Loop

JavaScript單線程和瀏覽器事件循環(huán)簡述

Javascript是單線程的深入分析

Concurrency model and Event Loop

也談setTimeout

單線程的Javascript


若這篇文章讓您獲益,歡迎您在 Github 給個(gè) Star。


本文鏈接:http://www.codeceo.com/articl...
本文作者:碼農(nóng)網(wǎng) – 劉健超
[ 原創(chuàng)作品,轉(zhuǎn)載必須在正文中標(biāo)注并保留原文鏈接和作者等信息。]

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/49719.html

相關(guān)文章

  • 細(xì)說JavaScript線程一些

    摘要:標(biāo)簽單線程首發(fā)地址碼農(nóng)網(wǎng)細(xì)說單線程的一些事最近被同學(xué)問道單線程的一些事,我竟回答不上。若以多線程的方式操作這些,則可能出現(xiàn)操作的沖突。另外,因?yàn)槭菃尉€程的,在某一時(shí)刻內(nèi)只能執(zhí)行特定的一個(gè)任務(wù),并且會阻塞其它任務(wù)執(zhí)行。 標(biāo)簽: JavaScript 單線程 首發(fā)地址:碼農(nóng)網(wǎng)《細(xì)說JavaScript單線程的一些事》 最近被同學(xué)問道 JavaScript 單線程的一些事,我竟回答不上。好...

    sarva 評論0 收藏0
  • js_Event Loop(筆記)

    摘要:單線程的好處簡單,處理時(shí)不會出現(xiàn)并發(fā)競爭問題異步的必要性讓用戶體驗(yàn)更流暢如何實(shí)現(xiàn)異步見參考,,調(diào)用棧函數(shù)執(zhí)行上下文。單線程只能有一個(gè)并且每次只能執(zhí)行一個(gè)任務(wù)。 參考: JavaScript 運(yùn)行機(jī)制詳解:再談Event Loop 深入理解JavaScript的執(zhí)行過程--單線程的JS 細(xì)說JavaScript單線程的一些事 The JavaScript Event Loop: Exp...

    liaoyg8023 評論0 收藏0
  • 前端計(jì)劃——JavaScript中關(guān)于setTimeout那些

    摘要:需要注意的是,及更早的瀏覽器不支持第一種語法中向延遲函數(shù)傳遞額外參數(shù)的功能。如果在不改變遞歸模式的前提下修善這段代碼解決方案加入定時(shí)器題目四考察和系列解釋立即的對象,是在本輪事件循環(huán)的結(jié)束時(shí),而不是在下一輪事件循環(huán)的開始時(shí)。 前言:setTimeout是JavaScript中常見的一個(gè)window對象方法,本文將介紹關(guān)于它的一些基礎(chǔ)知識和易出錯的地方。 1、基礎(chǔ)知識 作用:setTim...

    sihai 評論0 收藏0
  • 細(xì)說 Javascript 拾遺篇(四) : setTimeout 和 setInterval

    摘要:當(dāng)間隔時(shí)間設(shè)置較小時(shí),將會導(dǎo)致回調(diào)函數(shù)堆積。處理可能阻塞的代碼最簡單且最可控的方式就是在回調(diào)函數(shù)內(nèi)部使用函數(shù)。但是很明顯,由于指定最大值的限制,還會有定時(shí)器沒有被清除掉。另外,盡量避免使用函數(shù),從而避免可能導(dǎo)致的回調(diào)函數(shù)堆積現(xiàn)象。 由于 Javascript 是異步的,因此我們可以通過 setTimeout 和 setInterval 函數(shù)來指定特定時(shí)間執(zhí)行代碼。 function ...

    wangjuntytl 評論0 收藏0
  • JavaScript線程件循環(huán)(Event Loop)那些

    摘要:概述本篇主要介紹的運(yùn)行機(jī)制單線程事件循環(huán)結(jié)論先在中利用運(yùn)行至完成和非阻塞完成單線程下異步任務(wù)的處理就是先處理主模塊主線程上的同步任務(wù)再處理異步任務(wù)異步任務(wù)使用事件循環(huán)機(jī)制完成調(diào)度涉及的內(nèi)容有單線程事件循環(huán)同步執(zhí)行異步執(zhí)行定時(shí)器的事件循環(huán)開始 1.概述 本篇主要介紹JavaScript的運(yùn)行機(jī)制:單線程事件循環(huán)(Event Loop). 結(jié)論先: 在JavaScript中, 利用運(yùn)行至...

    Shisui 評論0 收藏0

發(fā)表評論

0條評論

coolpail

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<