• 【ES6】Promise的实现原理代码


    刚开始看 Promise 源码的时候总不能很好的理解 then 和 resolve 函数的运行机理,但是如果你静下心来,反过来根据执行 Promise 时的逻辑来推演,就不难理解了。这里一定要注意的点是:Promise 里面的 then 函数仅仅是注册了后续需要执行的代码,真正的执行是在 resolve 方法里面执行的,理清了这层,再来分析源码会省力的多。

    Promise 的实现过程,其主要使用了设计模式中的观察者模式:

    1. 通过 Promise.prototype.then 和 Promise.prototype.catch 方法将观察者方法注册到被观察者 Promise 对象中,同时返回一个新的 Promise 对象,以便可以链式调用。
    2. 被观察者管理内部 pending、fulfilled 和 rejected 的状态转变,同时通过构造函数中传递的 resolve 和 reject 方法以主动触发状态转变和通知观察者。
    //Promise 完整的实现
    class Promise {
      callbacks = [];//保存then中传入的回调函数
      state = 'pending';//增加状态
      value = null;//保存结果
      constructor(fn) {
        fn(this._resolve.bind(this), this._reject.bind(this));
      }
      then(onFulfilled, onRejected) {
    //实现Promise的链式调用,返回new Promise
    return new Promise((resolve, reject) => {
    //仅仅是注册了后续需要执行的代码,真正的执行是在 resolve 方法里面执行的
    this._handle({ onFulfilled: onFulfilled || null, onRejected: onRejected || null, resolve: resolve, reject: reject }); }); } catch(onError) { return this.then(null, onError); } finally(onDone) { if (typeof onDone !== 'function') return this.then(); let Promise = this.constructor; return this.then( value => Promise.resolve(onDone()).then(() => value), reason => Promise.resolve(onDone()).then(() => { throw reason }) ); } //Promise.resolve:用于将非 Promise 实例包装为 Promise 实例 static resolve(value) { if (value && value instanceof Promise) { return value; } else if (value && typeof value === 'object' && typeof value.then === 'function') { let then = value.then; return new Promise(resolve => { then(resolve); }); } else if (value) { return new Promise(resolve => resolve(value)); } else { return new Promise(resolve => resolve()); } } //Promise.reject:与 Promise.resolve 类似,区别在于 Promise.reject 始终返回一个状态的 rejected 的 Promise 实例 static reject(value) { if (value && typeof value === 'object' && typeof value.then === 'function') { let then = value.then; return new Promise((resolve, reject) => { then(reject); }); } else { return new Promise((resolve, reject) => reject(value)); } } //Promise.all:Promise.all 接收一个 Promise 实例的数组,在所有这些 Promise 的实例都 fulfilled 后,按照 Promise 实例的顺序返回相应结果的数组。 static all(promises) { return new Promise((resolve, reject) => { let fulfilledCount = 0 const itemNum = promises.length const rets = Array.from({ length: itemNum }) promises.forEach((promise, index) => { Promise.resolve(promise).then(result => { fulfilledCount++;
    //使用index实现根据请求顺序获取和使用数据的场景 rets[index]
    = result; if (fulfilledCount === itemNum) { resolve(rets); } }, reason => reject(reason)); }) }) } //Promise.race:也接收一个 Promise 实例的数组,与 Promise.all不同的是,所以返回的结果是这些 Promise 实例中最先 fulfilled 的。 static race(promises) { return new Promise(function (resolve, reject) { for (let i = 0; i < promises.length; i++) { Promise.resolve(promises[i]).then(function (value) { return resolve(value) }, function (reason) { return reject(reason) }) } }) } _handle(callback) { if (this.state === 'pending') { this.callbacks.push(callback); return; } let cb = this.state === 'fulfilled' ? callback.onFulfilled : callback.onRejected; if (!cb) {//如果then中没有传递任何东西 cb = this.state === 'fulfilled' ? callback.resolve : callback.reject; cb(this.value); return; } let ret; try { ret = cb(this.value); cb = this.state === 'fulfilled' ? callback.resolve : callback.reject; } catch (error) { ret = error; cb = callback.reject } finally { cb(ret); } } _resolve(value) { if(this.state !== 'pending') return if (value && (typeof value === 'object' || typeof value === 'function')) { var then = value.then; if (typeof then === 'function') { then.call(value, this._resolve.bind(this), this._reject.bind(this)); return; } } this.state = 'fulfilled';//改变状态 this.value = value;//保存结果 this.callbacks.forEach(callback => this._handle(callback)); } _reject(error) { if(this.state !== 'pending') return this.state = 'rejected'; this.value = error; this.callbacks.forEach(callback => this._handle(callback)); } }

    图解详细参照:https://zhuanlan.zhihu.com/p/58428287

  • 相关阅读:
    一个关于java线程的面试题
    【Feature】初探Feature
    Foreign Keys in the Entity Framework
    JS keycode
    SQLyog8.3 . 8.4 Enterprise/Ultimate crack
    Win7下使用toad连接oracle出现can't initialize OCI 1
    ADO 数据类型转换表
    简单Jscript(ASP)模版操作文件
    自适应宽度的左右结构DIV+CSS
    一个比较好用的 classic asp Jscript 框架 SmartAsp
  • 原文地址:https://www.cnblogs.com/vickylinj/p/14151494.html
Copyright © 2020-2023  润新知