你不知道的JavaScript 同步非同步
寫在前面的話
setTimeout是我們學習
JavaScript
基礎都必須面對的問題,也許當時你搞懂了,但是過一段時間就又忘記了。最近事情不多,我將梳理出for + setTimeout
相關的知識點,以及使用Promise
、async/await
來加深對非同步、同步的理解
setTimeout
直接進入正題:
for (var i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}
也許我們希望輸出的是
1,2,3,4,5
,但實際情況是我們輸出了5,5,5,5,5
,這到底是為什麼呢?
由JS的執行機制中我們得知:當執行緒中沒有任何同步程式碼的前提下才會執行非同步程式碼。我們的for迴圈時同步的,但是setTimeout是非同步的,由此就造成了輸出5,5,5,5,5
這種情況。
通過一頓胡亂分析我們得出假設:只要保證裡面的也變成同步的是不是就可以了呢?
方式①
for(var i = 0; i < 5; i++){
setTimeout(function(){
console.log(i);
}, i*1000)
}
這裡使用的是最簡單的方式:動態的改變延遲的時間。
因為for
迴圈時同步的,而setTimeout
是非同步的,所以會先把for
迴圈執行完畢,然後再執行內部的setTimeout
,所以輸出結果為每隔1
秒輸出一個5
方式②
for (var i = 0; i < 5; i++) {
(function(j){
setTimeout(function (){
console.log(j);
},1000);
})(i);
}
我們通過設定一個立即執行函式
(IIFE)
,這樣就能保證裡面和外面的是同步執行的。
方式③
function output(i){
setTimeout(function(){
console.log(i);
}, 1000)
}
for(var i = 0; i < 5; i++){
output(i);
}
這裡其實和第一種方法類似,只不過我們把這個函式單獨拿出來,並把
index
值當做函式的引數來傳遞
方式④
for(let i = 0; i < 5; i++){
setTimeout(function(){
console.log(i);
}, 1000)
}
let
是ES6
語法,for
迴圈程式碼塊構成一個作用域,裡面的內容引用了上層作用域的變數i
,並最終形成五個閉包,而for
使用var
時,還是ES5
的寫法,for
程式碼塊沒有形成作用域,所以裡面的function
不構成閉包。同理我們的方式①
和方式②
都形成了閉包函式。
如果我們需要最後一個延遲5
秒,其餘的都是延遲1
秒,我們就可以用到ES6
的語法--Promise,下面我們用Promise實現這一情況
方式⑤
const task = [];
const output = (i) => new Promise(function(resolve, reject){
setTimeout(function(){
console.log(i);
resolve();
}, i*1000)
})
for (var i = 0; i<5; i++){
task.push(output(i));
}
Promise.all(task).then(() => {
setTimeout(() => {
console.log(i);
}, 5000);
})
這裡採用了
Promise
解決非同步的方式,在ES7
中解決非同步還有async/await的方式
方式⑥
const sleep = (timeount) => new Promise((resolve) => {
setTimeout(resolve, timeount);
});
Func = async () => {
for(var i = 0; i<5; i++){
await sleep(1000);
console.log(i);
}
await sleep(5000);
console.log(i);
}
this.Func();
async
表示這是一個async
函式,await
只能用在這個函式裡面;await
表示在這裡等待promise
返回結果了,再繼續執行;await
後面跟著的應該是一個promise
物件,否則沒有同步效果
相關文章
- 同步非同步,阻塞非阻塞非同步
- 非同步、同步、阻塞、非阻塞非同步
- 同步、非同步、阻塞、非阻塞非同步
- 同步、非同步、阻塞、非阻塞的區別非同步
- 同步非同步 與 阻塞非阻塞非同步
- 理解阻塞、非阻塞、同步、非同步非同步
- 同步、非同步,阻塞、非阻塞理解非同步
- 同步、非同步、阻塞與非阻塞非同步
- 同步、非同步、阻塞和非阻塞非同步
- IO - 同步 非同步 阻塞 非阻塞的區別非同步
- 同步、非同步、阻塞、非阻塞的簡單理解非同步
- 同步與非同步、阻塞與非阻塞的理解非同步
- [轉]阻塞/非阻塞與同步/非同步非同步
- 同步與非同步 阻塞與非阻塞非同步
- 同步阻塞、同步非阻塞、多路複用的介紹
- javascript中同步和非同步JavaScript非同步
- 徹底搞懂同步非同步與阻塞非阻塞非同步
- java同步非阻塞IOJava
- 非同步和非阻塞非同步
- MySQL 主從同步架構中你不知道的“坑”(上)MySql主從同步架構
- 關於Handler同步屏障你可能不知道的問題
- 你好,JavaScript非同步程式設計—- 理解JavaScript非同步的美妙JavaScript非同步程式設計
- 你好,JavaScript非同步程式設計---- 理解JavaScript非同步的美妙JavaScript非同步程式設計
- 怎樣理解阻塞非阻塞與同步非同步的區別?非同步
- 那些你不知道的Dart細節之帶你透徹理解非同步Dart非同步
- 從同步原語看非阻塞同步以及Java中的應用Java
- 對於同步、非同步、阻塞、非阻塞的幾點淺薄理解非同步
- 如何解讀 Java IO、NIO 中的同步阻塞與同步非阻塞?Java
- Socket程式設計中的同步、非同步、阻塞和非阻塞(轉)程式設計非同步
- 你不知道的JavaScriptJavaScript
- 真正的 Tornado 非同步非阻塞非同步
- 大白話搞懂什麼是同步/非同步/阻塞/非阻塞非同步
- socket阻塞與非阻塞,同步與非同步、I/O模型非同步模型
- 網路IO之阻塞、非阻塞、同步、非同步總結非同步
- 你不知道的javascript,你不知道的奧祕JavaScript
- JavaScript非同步史JavaScript非同步
- JavaScript – 非同步的前世今生JavaScript非同步
- javascript非同步的發展JavaScript非同步