學習背景
實現nodejs的非阻塞IO就需要異步函數,之前我們講了異步的幾種實現方案。其中就說到了Promise的方案,這章呢我們詳細的講一講Promise方案的詳細用法,以及為什么nodejs要提供一個Promise。
Promise 用法
之前我們遇到了callback方法過多的話會形成回調地獄問題,這時我們的代碼就形成了一層一層的回調嵌套,就像洋蔥一樣。這時候變量作用域也不清晰了,執行時序問題也越來越亂,出現問題修改起來很痛苦,比如


看起來是不是絕望了。官方也發現了這個問題,所以引入了Promise。
Promise就是把異步函數轉變成一個對象,這個對象有自己的屬性以及方法。這個對象有著自己的狀態生命周期,也有自己的功能方法。
Promise字面理解是約定的意思,這個約定可以被實現也可以被拒絕。舉個簡單的例子吧,朋友約我今晚去打擼啊擼,我今天下班就陪他去了,履行了約定。還有一種可能性是公司臨時讓我加班,我沒時間去了,我只能失約了。
創建Promise
按照上面那個栗子,創建一個Promise代碼如下
// 第一步,我們創建一個去玩lol的約定
console.log('你下班陪我去打lol')
const playLolPromise = new Promise(
function (resolve, reject) {
let workOvertime = true // 是否加班
setTimeout(() => {
console.log('到下班時間了')
if (workOvertime) { // 加班了
reject(new Error('我加班了')) // 數據處理出錯
} else { // 沒有加班
resolve(true) // 數據處理完成
}
}, 100)
}
)
playLolPromise.then((res) => {
console.log('我沒加班,我準時來了')
console.log('我成功守約')
}).catch((e) => {
console.log('我沒有守約,因為:' + e.message)
}).finally(() => {
console.log('不管有沒有守約,我都要通知你')
})
沒加班運行結果
你下班陪我去打lol
到下班時間了
我沒加班,我準時來了
我成功守約
不管有沒有守約,我都要通知你
加班運行結果
你下班陪我去打lol
到下班時間了
我沒有守約,因為:我加班了
不管有沒有守約,我都要通知你
可以看出Promise通過new 關鍵字創建,創建的時候有兩個參數reject和resolve,它兩是一個方法,當需要成功守約的時候把結果傳給resolve,如果要失約的話把原因傳給reject。
Promise的三個狀態
Promise有三個狀態:
- 1、pending[約定好]初始狀態,代表約定任務還沒執行
- 2、resolved[守約]代表守約了
- 3、rejected[違約]代表違約了
promise狀態只會變化一次,要么是從pending到resolved成功守約狀態,要么是pending到rejected失約狀態
resolve 守約
它的作用是將Promise對象的狀態從“約定”變為“守約”(即從 pending 變為 resolved),在異步操作成功時調用,并將異步操作的結果,作為參數傳遞出并觸發約定的then和finally方法.
reject 違約
作用是,將Promise對象的狀態從“約定”變為“失約”(即從 pending 變為 rejected),在異步操作失敗時調用,并將異步操作報出的錯誤,作為失敗原因傳遞出去并觸發約定的catch和finally方法。
Promise 的常用方法
Promise.resolve 現有對象轉為Promise對象并完成守約
const promise = Promise.resolve('我沒加班')
// 等價于
// const promise = new Promise(resolve => resolve('我沒加班'))
promise.then((res)=>{
console.log('我守約了:'+res) // 打印“我守約了:我沒加班”
})
Promise.reject 現有對象轉為Promise對象并失約,并設置失約原因
const promise = Promise.reject('我加班了')
// 等價于
// const promise = new Promise((resolve,reject) => reject('我加班了'))
promise.catch((reason)=>{
console.log('我失約了:'+reason) // 打印“我失約了:我加班了”
})
Promise.all([p1,p2,p3…]) 將多個Promise實例包裝成一個新的Promise實例,并將結果合并為同序數組
成功和失敗的返回值是不同,成功的時候返回的是一個結果數組,這個結果數組的順序和傳入的promise順序一致,而失敗的時候則只會返回最先被reject失敗狀態的值。
Promise.race([p1,p2,p3….])將多個Promise實例包裝成一個新的Promise實例,返回最快的結果,不過這個不常用
callback轉成Promise
把fs.unlink轉成Promise
let unlinkPromise = function(filePath) {
return new Promise(function(resolve, reject) {
fs.unlink(filePath, (err) => {
if(err) return reject(err);
return resolve();
})
})
}
// 等價于
const util = require('util')
let unlinkPromise = util.promisify(fs.unlink);
最后
這一章我們我們需要重點掌握Promise的概念以及如何創建Promise,nodejs官方大力推薦Promise的解決方案,并提供了async 和await的語法糖來實現以同步的方式寫異步方法.來讓我們js代碼看起來更舒服更容易維護.下一章我將教大家async 和await是如何與Promise搭配使用的.
版權聲明:本文內容由互聯網用戶自發貢獻,該文觀點僅代表作者本人。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如發現本站有涉嫌抄襲侵權/違法違規的內容, 請發送郵件至 舉報,一經查實,本站將立刻刪除。