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 了,而这种恶意作法的成本要比他不当心多复制一行代码的成本要高得多。