ES6 Promise 執行解析

sandy_anqi發表於2019-03-04

作為一門單執行緒的語言,剛學習 JavaScript 語言的時候,我曾懷疑過 JavaScript 在處理 ajax 資料請求,檔案解析等過程效率會很低,而且在執行這些任務較大的程式碼中,會嚴重阻塞後面程式碼的執行。但讓人興奮的是,這門語言具有非同步載入的特性。

事件迴圈

1. 含義

javascript 提供一種機制來處理程式中多個塊的執行,且每個執行塊都呼叫了 JavaScript 引擎,這種機制被稱為事件迴圈。

2. setTimeout

setTimeout 在不清楚它的呼叫機制的時候,可能會容易掉坑。一定要清楚的是,setTimeout 執行的時候,並沒有把回撥函式放入事件迴圈佇列中,它做的事情只是設定一個定時器,當時間到時後,環境才會把回撥函式加入到事件迴圈佇列中

考慮下面的例子
setTimeout(function(){
    console.log("setTimeout")
},0)
console.log("console")
// console,setTimeout
複製程式碼

根據 setTimeout 的執行機制,這個例子的先後執行順序就一目瞭然了。即便 setTimeout 的定時器時間為0,但是因為事件迴圈機制,且考慮到瀏覽器實行的延遲作用,setTimeout 依舊還是會慢與外界的 console。

回撥

1.含義

回撥是編寫和處理 JavaScript 程式非同步邏輯最常用的方式。

2.巢狀回撥和鏈式回撥

考慮:

listen('click',function handle(){
    setTimeout(function request(){
        ajax('http:XXX',function response(data){
            if(data.code===200){code...}
            else{code...}
        })
    },
    500)
})
複製程式碼

在我初學 javascript 的時候,常寫這種函式巢狀在一起構成一條鏈的程式碼,因為它能按照我們想要執行的順序執行,但是這種程式碼在巢狀多層的時候是很容易讓人混亂的,這種程式碼常常被稱為回撥地獄

不用巢狀將上述程式碼重寫,可寫為:

listen('click',handle)
function handle(){
    setTimeout(request,500)
}
function request(){
    ajax('http:XXX',response)
}
function response(data){
    if(data.code===200){code...}
    else{code...}
}
複製程式碼

3.總結

通過上述例子我們可以初步的理解回撥的意義,下面將會講解非同步最常使用的 Promise。

Promise

1.含義

Promise(譯為期望,期待),是一種封裝和組合未來值的易於複用的機制;

2.語法

下面程式碼創造了一個 Promise 例項

const myPromise = new Promise(function(resolve,reject){
    // ...code
    if(/非同步執行成功/) {
        resolve(value)
    } else {
        //非同步執行失敗
        reject(error)
    }
複製程式碼

resolve函式的作用是,當 Promise 的狀態由未完成轉變為成功時呼叫的函式,reject函式的作用是,當 Promise 的狀態由未來城轉變為失敗時呼叫的函式 Promise 例項生成後,可以使用 then 方法分別指定 resolved 狀態和 rejected 狀態的回撥函式

myPromise.then(function(value){
    // success
    },function(error){
        //error
    }
)
複製程式碼

then的方法可以接收兩個引數,第一個回到函式是當 Promise 狀態變為成功 resolved 時呼叫,第二個回撥函式是當 Promise 狀態變為失敗 rejected 時呼叫,第二個引數是可選的,非必須的

3.實戰練習

根據上面的事件迴圈機制,以及 Promise 的語法,考慮下方程式碼:

let myPromise = new Promise(function(resolve,reject){
    console.log("promise");
    resolve()
})
myPromise.then(function(){
    console.log("resolved.")
})
console.log("consolelog")
// promise
//consolelog
//resolved.
複製程式碼

上面程式碼中,Promise 新建後立即執行,所以首先輸出的是 “Promise”,然後,then 方法指定回撥函式,將當前指令碼所有同步任務執行完之後再呼叫,所以 ,然後輸出 “consolelog”,最後執行 then ,輸出“resolved."

進而再考慮下面程式碼:

setTimeout(function(){console.log("setTimeout")},0)
let myPromise = new Promise(function(resolve,reject){
    console.log("promise");
    resolve()
}).then(function(){
    console.log("resolved.")
})
console.log("consolelog")
// promise -> consolelog -> resolved. -> setTimeout
複製程式碼

這段程式碼即是上面程式碼加上 setTimeout ,原理是相同的,因為 setTimeout 存在延遲,即便延遲時間為0,它都不屬於 Promise 所在的同步任務事件佇列中,所以,setTimeout 會在最後執行。

總結

本文主要講解了 javascript 的事件迴圈機制,程式碼自上而下執行過程中,是存在非同步執行的過程的,但在當前所有同步任務的執行依舊是自上而下的。另外,本文主要講解了 Promise 的主要用法,詳情可以參照 es6.ruanyifeng.com/#docs/promi…


猜歡迎大家在留言區探討更多的  Promise 使用~

喜歡的點個讚唄~

猜你喜歡

ES6 箭頭函式 www.jianshu.com/p/24d488844…

ES6 生成器 generator www.jianshu.com/p/91673eab0…



相關文章