Promise不懂?一篇文章带你弄懂promise(包含promise源码)

145 阅读4分钟

在开篇之前,小编想说句篇外话,ES6中新增的语法。你知道多少呢?如果觉得自己了解的不太全面可以跟着这个网址去复习一下,小编觉得非常有用。es6.ruanyifeng.com/

Promise是ES6新增一个内置类,可以理解为它是承诺者模式,Promise对象用于表示一个异步操作的最终完成(成功或者失败),以及结果的值。它主要是为了有效管理异步编程,存在的目的就是为了解决回调地狱

什么是回调地狱?

基于ajax的请求,完成需求为请求三个接口(@1:/api/list&@2/api/detail?id=100&@3/api/ranking),带你理解什么是回调地狱。首先先看一段代码:

		url:'api/list',
		success(){
			// 第一个请求成功,触发了success回调函数
			$.ajax({
				url:'/api/detail?id=100',
				success(){
					// 第二个请求成功
					$.ajax({
						url:'/api/ranking',
						success(){
							// 第三请求成功
						}
					})
				}
			})
		}
	})

这是ajax的串行:也就是多个请求之间有依赖。只有完成上一个请求,才能发送下一个请求。代码中,代码一层圈套一层。为了实现代码顺序执行而出现的一种操作,它会造成我们的代码可读性非常差,后期不好维护。这就是回调地狱。

创建Promise实例的几种方法:
  • 一:通过new Promise ((executor))

注意:executor函数执行看是否报错,如果报错则返回是失败的,失败的原因就是报错的原因。但是不报错的不一定成功,它会接着走下一步。

在这里小编对executor函数做一个扩展,帮助你更好的掌握Promise

  1. 必须传递的是一个函数,不传或者传递其他类型值都会报错

  2. new promise的时候会立即把传递的executor函数执行,这个操作是的同步的. new Promise(()=>{ console.log(1); }); console.log(2)它的输出结果就是1,2

  3. 在executor函数中,一般来写一些易怒的编程代码(promise管理异步编程,其实就是把异步编程的代码放在executor中

[executor]函数中有两个形参:   resolve/reject(本身也都是个函数)

resolve([value])把时刻状态改为fulfilled,实例值是[value]

reject([reason])把实例状态改为rejected,实例值是[reason]

一旦实例状态被改变为成功和失败,不可以再次更改

[executor]函数执行一旦报错,实例的状态也是rejected,实例的值就是报错原因

  • 二:通过.then实例创建 let @p=实例.then([[onfulfilled]],[[onrejected]])

在这里说明一下.then和.catch的区别
.then后面接的是([[onfulfilled]],[[onrejected]])
.catch后面接的是([onjected]) 因为catch会对错误进行兜底,就是抛出的任何异常时都会进入到catch中。 then链具备“穿透性”如果onfulfilled或者onrejected没有设置,则会顺延到下一个then对应的onfufilled或者onrejected上!!

  • 三:通过.catch创建 let @p=实例.catch([[onrejected]])

1.@p是执行then/catch返回的新实例

2.不论是onfulfilled还是onrejected执行。我们关注的是执行是否报错,返回值来决定@p的状态和值。方法执行只要报错@p就是rejected,值就是报错的原因,返回值不是一个新的promise实例,则@p就是fulfilled值就是返回结果。如果返回的是一个新的promise实例(@new)则@new的状态和值决定了@p的状态和值

3.如果两个方法中的某个方法没有传递,则"顺延"到下一个[then的穿透机制]

  • 四:创建一个状态为成功的promise实例(fulfilled) Promise.resolve([[value]]) 创建一个状态为失败的promise实例(rejected) Promise.resolve([[reason]]) Promise.all([[paomise]]) 创建一个实例,当[[promises]]当集合中的每一项实例都是成功,最后整体返回的就是成功(值:按照顺序,储存了集合中每一项成功的结果)其中只要又一项是失败的,整体返回就是失败的(值:谁失败,获取的结果就是谁失败的原因,只要有一项失败了,则处理结果就结束了)
  • 五:还有许多创建Promise的方法 Promise.race/any...

这里是关于一些创建Promise的一些基础知识,了解过基础知识,接下来就跟着小编去看一些源码,来帮助你更深层次的掌握Promise

源码部分
    // 首先为了防止冲突,将promise源码采用闭包的形式保护起来
	(function () {
    /* 核心 */
    function Promise(executor) {
    // 对Promise进行检测,检测executor是不是一个函数以及检测Promise是不是一个实例
        var self = this;
        if (typeof executor !== "function") throw new TypeError("Promise resolver is not a function");
        if (!(self instanceof Promise)) throw new TypeError("undefined is not a promise");
        // 给Promise 设置私有属性
        self.state = "pending";
        self.result = undefined;

        self.onfulfilledCallback = [];
        self.onrejectedCallback = [];
        var change = function change(state, result) {
            // 修改实例的状态和值(同步) & 通知集合中指定的方法执行(异步)
            if (self.state !== "pending") return;
            self.state = state;
            self.result = result;
            setTimeout(function () {
                var callback = state === "fulfilled" ? self.onfulfilledCallback : self.onrejectedCallback;
                for (var i = 0; i < callback.length; i++) {
                    callback[i](self.result);
                }
            });
        };
        // 立即执行executor函数
        try {
            executor(function resolve(value) {
                change('fulfilled', value);
            }, function reject(reason) {
                change('rejected', reason);
            });
        } catch (err) {
            change('rejected', err);
        }
    }
    Promise.prototype = {
        constructor: Promise,
        then: function then(onfulfilled, onrejected) {
            var self = this;
            switch (self.state) {
                case "fulfilled":
                    setTimeout(function () {
                        onfulfilled(self.result);
                    });
                    break;
                case "rejected":
                    setTimeout(function () {
                        onrejected(self.result);
                    });
                    break;
                default:
                    self.onfulfilledCallback.push(onfulfilled);
                    self.onrejectedCallback.push(onrejected);
            }
        },
        catch: function myCatch() { }//注意catch这里命名方式,遵循js中的命名规范
    };
    // 暴露API:即支持CommonJS模块规范也支持浏览器直接导入 >处理兼容问题
    if (typeof module === "object" && typeof module.exports === "object") module.exports = Promise;
    if (typeof window !== "undefined") window.Promise = Promise;
})();