文章目录
前言
解决异步编程回调地狱问题的解决方案Promise、Generator和async/await已被ES6收录,发布/订阅和deferred对象是社区中的解决方案。本篇文章重在深入理解Promise,手写一个Promise方法。
序号 | 资料名称 | 链接 | 备注 |
---|---|---|---|
1 | Promise介绍 | https://es6.ruanyifeng.com/#docs/promise | |
2 | promise 基础 | https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise | |
3 | promises A+规范 | https://github.com/promises-aplus/promises-spec | |
4 | promises A+规范测试工具用例工具 | https://github.com/promises-aplus/promises-tests |
一、什么场景下需要使用Promise?
处理多个异步请求( 回调嵌套/回调地狱/回调金字塔 )
二、Promise解决了什么问题?
1. 回调地狱(Promise的链式结构并为完全解决这个问题)
2. 可靠性丢失
当我们使用第三方库提供的异步方法时,我们希望有以下几点(提高可靠性):
1. 不会太早调用我的回调函数;
2. 不会太迟调用我的回调函数;
3. 会给我的回调提供必要的参数;
4. 在我的回调失败的时候会提醒我。
当我们使用多个第三方库,而其中的库又调用其他的库的异步方法时,可靠性丢失的问题尤为重要。Promise就是解决这个问题的。
三、Promise是如何解决问题的?
一个 Promise 必然处于以下几种状态之一:
待定(pending):初始状态,既没有被兑现,也没有被拒绝。
已兑现(fulfilled):意味着操作成功完成。
已拒绝(rejected):意味着操作失败。
待定状态的 Promise 对象要么会通过一个值被兑现,要么会通过一个原因(错误)被拒绝。当这些情况之一发生时,我们用 promise 的 then 方法 排列起来的相关处理程序就会被调用。如果 promise 在一个相应的处理程序被绑定时就已经被兑现或被拒绝了,那么这个处理程序也同样会被调用,因 此在完成异步操作和绑定处理方法之间不存在竞态条件。
因为 Promise.prototype.then 和 Promise.prototype.catch 方法返回的是 promise,所以它们可以被链式调用。
一个 Promise 对象代表一个在这个 promise 被创建出来时不一定已知值的代理。
它让你能够把异步操作最终的成功返回值或者失败原因和相应的处理程序关联起来。
这样使得异步方法可以像同步方法那样返回值:异步方法并不会立即返回最终的值,而是会返回一个 promise,以便在未来某个时候把值交给使用者。
通过Promise,我们重新获得了程序的控制权,而不是通过给第三方库传递回调来转移控制权。
更为详细的内容可查看学习资料链接:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise
四、Promise的缺点?
1. 无法取消Promise,一旦新建他就会立即执行,无法中途取消;
2. 如果不设置回调函数,Promise内部抛出的错误,不会反映到外部;
3. 当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
五、Promise的常用方法及其作用?
参看学习资料1链接:https://es6.ruanyifeng.com/#docs/promise
六、如果浏览器不知道Promise应该如何处理?
实现一个简单的Promise-polyfill(polyfill用于实现浏览器并不支持原生API的代码)。
promise/A+规范是一个开放的标准,对于开发人员可互操作的JavaScript promise。
promise状态要求:
1. promise对象代表一个异步操作,有三种状态:pengding(进行中)、fulfilled(已成功)和reject(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
2. 一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。
then方法要求:
1. 一个promise必须提供一个then方法,用来获取当前异步操作的value或error。
2. 一个promise的then方法接收两个参数:promise.then(onFulfilled, onRejected)。
3. then方法返回的是一个新的promise实例(注意,不是原来那个promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法。
4. onFulfilled, onRejected有可能返回的还是一个promise对象(即有异步操作),这时 后一个回调函数,就会等待该promise对象的状态发生变化,才会被调用。
promises A+规范:https://github.com/promises-aplus/promises-spec
container容器:
//(Promise-polyfill)手写符合Promise/A+规范的Promise
//promise.js
//(Promise-polyfill)手写符合Promise/A+规范的Promise
//promise.js
var cache = {
}; // 缓存对象
var container = function (flags) {
//flags标记 once;memory;stopOnFalse
// once只执行一次;
// memory调用startup之后再调用startup会立即执行(也就是不在执行上边已经执行过的了);
// stopOnFalse遇到暂停属性的值为false时,暂停执行(也就是设置了stopOnFalse的值为false,后边的回调就不执行了)
flags = typeof flags == "string" ? (cache[flags] || createFlags(flags)) : extend({
}, flags);
var carryOut, len, i, memory, stackLen, stackPoint;
//carryOut记录回调是否调用过;
//len是stack的长度;
//stackLen记录最后一次执行add方法前的stack的长度;
//stac