Promise ,為什麼會出現它,Promise 的出現,解決了哪些問題呢?
- 解決了回撥地獄(巢狀)的問題,不會導致難以維護。
- 解決同步&非同步的返回結果,並且按照順序返回
大家應該都知道,在 JavaScript 的世界裡,所有程式碼的執行都是單執行緒操作的。由於這個問題,導致 JavaScript 所有請求操作都必須非同步執行。
Promise 本意是承諾,在程式中的意思就是承諾我過一段時間後給你返回一個結果。什麼時候會用到(多一段時間)?那就是(非同步操作),非同步是指過了很長時間後才會返回結果。比如 網路請求、讀取本地檔案等~
基本用法
首先,我們去控制檯列印一下 Promise,如圖
很直觀的看出來,Promise 是一個建構函式- Promise 物件擁有兩種例項方法(prototype):then() 和 catch() 。
- Promise 還擁有四個靜態方法,分別是:all、race、reject、resolve。
我們粘一段程式碼,小白如何呼叫 Promise
// 引入 Promise 模組
let Promise = require('promise')
let p = new Promise(function(resolve, reject){
// 如果同時呼叫成功和失敗的方法,那麼執行順序就是:誰在前,就調誰。
reject(100);
resolve(1);
})
// then 接受兩個回撥函式,一個是成功的回撥,一個是失敗的回撥
p.then(function(data){
console.log('data', data)
},function(err){
console.log('err', err)
})
// 控制檯列印的結果為:data 100
複製程式碼
接下來我們來看看 Promise 有哪些 API
then() 方法
從例子中可以看出 then 方法可以接收兩個引數,且通常都是函式。第一個引數是成功的回撥,第二個引數是失敗的回撥。這兩個引數都會將回撥存放在對應的陣列內,當 promise 狀態改變之後,呼叫成功或者失敗的陣列即可
- then 方法可以鏈式呼叫,與 jquery 不同,jquery 的鏈式呼叫靠的是返回的 this,可惜的是, promise 不能返回 this,promise 實現鏈式呼叫靠的是返回一個新的 Promise
let p = new Promise(function(resolve, reject){
resolve()
})
// p2 和 p 不是一個東西,如果是,就會走成功了。就不會走失敗了
let p2 = p.then(function(){
throw new Error('錯誤')
})
p2.then(function(data){
console.log(data)
},function(err){
console.log(err)
})
// 控制檯列印結果:Error: 錯誤
複製程式碼
- promise 例項可以多次 then,當成功後,會將 then 中的成功方法按順序執行
let p = new Promise(function(resolve, reject){
// 定時器來非同步回撥
setTimeout(function(){
resolve(1000)
}, 1000)
})
p.then(function(data){
console.log('data', data)
},function(err){
console.log('err', err)
})
p.then(function(data){
console.log('data', data)
},function(err){
console.log('err', err)
})
// 列印結果:
data 1000
data 1000
複製程式碼
catch() 方法
它有兩個作用:
- 可以和 then 的第二個引數一樣,用來指定 reject 的回撥
- 執行 then 第一個回撥引數時,如果丟擲異常,會直接走 catch 方法
let p = new Promise(function(resolve, reject){
reject(new Error('error'))
})
// then 沒有寫第二個 reject 回撥
p.then(function(data){
console.log(data)
}).catch(function(reasone){
console.log(reasone)
})
// 列印結果: Error: error
複製程式碼
resolve() & reject() 方法
- Promise.resolve() 相當於建立了一個立即 resolve 物件,使得 promise 物件直接 resolve。
Promise.resolve(5).then(function(data){
console.log(data)
})
// 列印結果:5
複製程式碼
- Promise.reject() 相當於建立了一個立即 reject 物件,使得 promise 物件直接 reject,並把 error 傳到 catch 函式中
Promise.reject(new Error('error')).catch(function(err){
console.log(err)
})
// 列印結果:Error: error
複製程式碼
all() 方法
- Promise.all() 接收的引數是 promise 物件組成的陣列,並返回新的 promise 物件。
Promise.all([Promise.resolve(100),Promise.resolve(200)]).then(function(data){
console.log('成功:',data)
},function(err){
console.log(err)
})
// 列印結果:成功: [ 100, 200 ]
複製程式碼
- 當陣列中有一個 reject 時,會改變狀態,並執行錯誤狀態
Promise.all([Promise.resolve(100),Promise.reject(new Error('error'))]).then(function(data){
console.log('成功:',data)
},function(err){
console.log(err)
})
// 列印結果:Error: error
複製程式碼
race() 方法
- Promise.race() 同樣接收的引數是 promise 物件組成的陣列,並返回新的 promise 物件。與 Promise.all() 不同的是隻要第一個陣列成功了。就算成功。如果第一個失敗了。就算失敗
// 成功的狀態,第一個陣列物件,成功了就不會執行下一個陣列物件
Promise.race([Promise.resolve(100),Promise.reject(new Error('error'))]).then(function(data){
console.log('成功:',data)
},function(err){
console.log(err)
})
// 失敗的狀態,第一個陣列物件失敗,就會報錯,後面也不執行
Promise.race([Promise.reject(new Error('error')),Promise.resolve(100),Promise.reject(new Error('error'))]).then(function(data){
console.log('成功:',data)
},function(err){
console.log(err)
})
複製程式碼
友情連結
- Promise 原始碼實現:www.jianshu.com/p/7754f0182…
- Promise 物件:es6.ruanyifeng.com/#docs/promi…