TL;DR
本文是對Promise
一些概念點的概括和對Promise
在解決什麼問題的思考。
並不會介紹Promise
的 Api。html
一直想寫一篇關於 Promise
的文章,但以爲本身對 Promise
是隻知其一;不知其二,始終擱置。前幾天恰好在看 Dr. Axel Rauschmayer
的『 Exploring ES6 』 這本書的時候,看到關於 Promise
的章節,仔細讀了一遍,又動手實現了簡易版的 Promise
一遍,再印證其它的資料,這纔開始完成這篇文章。es6
Promise
哪些知識點const p = new Promise( function (resolve, reject) { // (A) ··· if (···) { resolve(value); // success } else { reject(reason); // failure } })
A 行的函數被稱爲 executor
promise
當實例化一個 Promise
的時候,executor
老是「當即執行」的服務器
Promises
老是異步執行的。在 then 的消耗 Promise
value 時候,會把 then 的參數放到任務隊列中,等待執行。異步
當 Promise
中的狀態進入穩定態(settled)的時候,Promise
的值便不會再發生變化,這就是 Promise
的名稱由來:承諾。函數
// executor 當即執行的驗證 new Promise( (res) => { console.log(1) setTimeout(() => console.log(3), 1000) }) console.log(2) // ------> 1 // ------> 2 // ------> 3 // then 的參數是異步調用的驗證 new Promise( (res) => { res(2) }).then(v=> console.log(v)) console.log(1) // ------> 1 // ------> 2 // 當在 executor 中經過調用 res 使狀態穩定以後,無論調用多少次 res,值都不會再發生變化 new Promise( (res) => { res(1) res(2) }).then(v=> console.log(v)) // ------> 1
Promise
-- 一言既出;駟馬難追Promise
的優勢是什麼?我看了不少文章在介紹 Promise
的時候都會提到回調噩夢(Callback Hell
)。然而我以爲 Promise
並無簡單的解決回調噩夢的問題,寫 then 每每比寫 callback 更噁心。ui
在我看來,Promise
提供了控制反轉的機會。spa
假設有下面這樣一個函數,10 秒後調用傳入的 fn。這是一個你的同事提供給你的獨立文件。日誌
// foo.js function foo(fn) { setTimeout(fn, 1000*10) } module.exports = foo
你在寫一個 10 秒以後打印 log 的業務:code
var foo = require('foo') foo(()=> console.log('hello,world!!'))
然而很不幸,你的同事離職,他的代碼被交給一個很笨的新同事維護,新同事維護這個代碼的時候,不當心複製了一行代碼:
// foo.js function foo(fn) { setTimeout(fn, 1000*10) setTimeout(fn, 1000*10) } module.exports = foo
這時每次調用 foo 的時候,都會寫兩遍日誌,不到 1 天服務器的硬盤就被撐爆了,用戶就不能訪問網頁了,接着用戶就流失了,公司倒閉了,你就被失業了,想一想都是很可怕的事情。這些都是由於你把你的函數交給你的同事調用而且無條件信任他。
然而 Promise
會怎樣作?
// foo.js function foo() { return new Promise((res) => { setTimeout(res, 1000*2) }) } module.exports = foo // main.js var foo = require('foo') foo().then(()=> console.log('hello,world!!'))
那個笨同事又幹了一樣的蠢事,此次他複製了三行:
// foo.js function foo() { return new Promise((res) => { setTimeout(res, 1000*10) setTimeout(res, 1000*10) setTimeout(res, 1000*10) }) } module.exports = foo
然而此次讓我失業的行爲並無得逞,由於當 Promise
的狀態穩定以後,值就不會再改變,無論調用多少次 reslove 方法都是一樣的效果。Callback 會把你作的事情的權限交出去,你再也不對你的函數有控制權,而 Promise 是在等狀態穩定以後纔會再去執行你本身的函數,你對此函數擁有控制權。
不過說到底,都沒有絕對的信任,也說不定有人會把 Promise
的 then 實現 hack 了,而這種惡意作法的成本要比他不當心多複製一行代碼的成本要高得多。