JavaScript
異步編程for(var i = 0; i < 3; i++) { setTimeout(function() { console.log('timeout' + i); }) } new Promise(function(resolve) { console.log('promise1'); for(var i = 0; i < 1000; i++) { i == 99 && resolve(); } console.log('promise2'); }).then(function() { console.log('then1'); }) console.log('global1'); promise1 promise2 global1 then1 3 timeout3
JavaScript
單線程在瀏覽器的一個頁面中,該頁面的JS程序只有一個線程,故曰單線程。由於是單線程,因此程序的執行順序就是從上到下依次執行,同一時間內只能有一段代碼被執行。javascript
瀏覽器的渲染進程是多線程的html
瀏覽器渲染進程圖:
java
for (var i = 0; i < 5; i ++) { setTimeout(function(){ console.log(i); }, 0); } console.log(i); //5 ; 5 ; 5 ; 5; 5
Callback
這是異步編程最基本的方法。面試
假定有兩個函數f1和f2,後者等待前者的執行結果。編程
f1(); f2();
若是f1
是一個很耗時的任務,能夠考慮改寫f1
,把f2
寫成f1
的回調函數。\promise
function f1(callback){ setTimeout(function () { // f1的任務代碼 callback(); }, 1000); }
執行代碼就變成下面這樣:瀏覽器
f1(f2);
採用這種方式,咱們把同步操做變成了異步操做,f1
不會堵塞程序運行,至關於先執行程序的主要邏輯,將耗時的操做推遲執行。多線程
回調函數的優勢是簡單、容易理解和部署,缺點是不利於代碼的閱讀和維護,各個部分之間高度耦合Coupling
,流程會很混亂,並且每一個任務只能指定一個回調函數。app
發佈-訂閱模式又叫作觀察者模式,他定義了一種一對多的依賴關係,即當一個對象的狀態發生改變的時候,全部依賴他的對象都會獲得通知。異步
let yourMsg = {}; yourMsg.peopleList = []; yourMsg.listen = function (fn) { this.peopleList.push(fn); } yourMsg.triger = function () { for(var i = 0,fn;fn=this.peopleList[i++];){ fn.apply(this,arguments); } } yourMsg.listen(function (name) { console.log(`${name}收到了你的消息`); }) yourMsg.listen(function (name) { console.log('哈哈'); }) yourMsg.triger('張三'); yourMsg.triger('李四');
Promise
Promise
是一個對象,它表明了一個異步操做的最終完成或者失敗。
Promise 最
直接的好處就是鏈式調用(chaining
)
const promise = new Promise(function(resolve, reject) { // ... some code if (/* 異步操做成功 */){ resolve(value); } else { reject(error); } });
Generators/ yield
Generator
function* Hello() { yield 100 yield (function () {return 200})() return 300 } var h = Hello() console.log(typeof h) // object console.log(h.next()) // { value: 100, done: false } console.log(h.next()) // { value: 200, done: false } console.log(h.next()) // { value: 300, done: true } console.log(h.next()) // { value: undefined, done: true }
yield
yield
關鍵字使生成器函數執行暫停,yield
關鍵字後面的表達式的值返回給生成器的調用者。它能夠被認爲是一個基於生成器的版本的return
關鍵字。
function* countAppleSales () { var saleList = [3, 7, 5]; for (var i = 0; i < saleList.length; i++) { yield saleList[i]; } } var appleStore = countAppleSales(); // Generator { } console.log(appleStore.next()); // { value: 3, done: false } console.log(appleStore.next()); // { value: 7, done: false } console.log(appleStore.next()); // { value: 5, done: false } console.log(appleStore.next()); // { value: undefined, done: true }
async/await
async function func() { try { let res = await asyncFunc() } catch (e) { //...... } }
async
函數返回的 Promise
對象,必須等到內部全部的 await
命令的 Promise
對象執行完,纔會發生狀態改變
async
函數的語法不難,難在錯誤處理上。
https://juejin.im/post/5a6547...
http://www.ruanyifeng.com/blo...
https://juejin.im/post/5a1681...
https://juejin.im/post/5ce75f...
https://developer.mozilla.org...
https://juejin.im/post/596e14...