Fork me on GitHub

Coding Poineer

Coding Poineer

Coding Poineer

Coding Poineer

Coding Poineer

Coding Poineer

Coding Poineer

Coding Poineer

Coding Poineer

Coding Poineer

Coding Poineer

promise源码解析,及setTimeout、async执行顺序比较

Document
  • javaScript是单线程,一个线程只有唯一的事件循环,每一个任务必须执行完才能进行下一个任务

    • 同步任务

      • 主线程上直接按顺序执行
    • 异步任务

      • 不在主线程中,而是在“任务队列”中
      • 只有任务队列通知主线程,异步任务才能进入主线程执行
        • 宏任务(macro-task):
          • script(整体代码) | setTimeout | setInterval | setImmediate | I/O | UIrendering

            1. script=> 最外层的宏任务被放入主线程立即执行,因为此时还没有微任务来竞争
            2. setTimeout:时间到期后执行的函数放在宏任务队列(会在所有的微任务执行完再考虑率)
              • 第2个参数:0,事实不会有0,之前默认最小10ms/现在4ms
        • 微任务(micro-task):
          • process.nextTick | Promise | MutationObserver
          • setTimeout()、new promise()、async 如果给的参数是表达式,会直接执行
      • setTimeout,时间到期后,函数加到宏任务队列

        • (需等到没有微任务、前面的宏任务执行完才能执行)
        • 第二个时间参数只是函数等待执行的最短时间,0会自动转换成4,之前是10
      • 新产生的promise会被放到微任务队列中(前面的微任务执行完就可以执行)
      • async、await

        • async:后面接函数/函数表达式,函数的返回值作为 Promise.resolve() 的参数,产生一个promise对象
        • await:等,如果后面是普通表达式,直接执行通过 / 如果是promise对象相当于then,添加到微任务队列
          • await后续的代码会作为下一个then中的代码等待await这一步的then执行完

    问题:在 ES6 以前不支持 Promise 的环境下,通常只能靠 setTimeout 回退到传统的 Task 来模拟 Promise。但实际业务中,并没有感受到此类没有依赖微任务的 polyfill 有什么严重的可用性问题

    • 问题解释:模拟的Promise (根据前文提示:promise产生微任务) 是通过ES5的setTimeout (到期后产生宏任务) 没有产生问题
    • 那么接下来需要解决就是:原生的promise的执行顺序是否被模拟实现的promise都完成
    • process.Nextick: 其产生的任务在所有微任务之前,故执行顺序慢的promise由宏任务(setTimeout)或微任务(原生Promise)都不影响 (!在座的各位都是辣鸡!)
    • 同级别promise: 因为都是同级别,一起由微任务降为宏任务,相对顺序没有变化
    • setTimeout
      • 这个地方可能会有bug。比如前面也有setTimeout(fn,0),模拟promise不能先执行,会在后面执行
      • 但是正常情况下,也不会出现setTimeout(fn,0)的代码

promise执行过程解析

  1. new Promise(fn(res,rej){执行体}) => fn直接执行
  2. 执行体没有:resolve() / rejected
    • game over,后面的then中的函数不会执行
      1. p.then(console.log('????????')):仍然会输出
      2. then里面的代码仍然是通过 new promise(fn) fn执行
      3. fn如果返回then,可以继续.then/value则传给后面的then中的函数作为参数
  3. 执行体有:resolve() / rejected
    • state被改变,后续的then可以执行
  4. class Promise {
      constructor(executor) {
        console.log(executor);
        this.state = 'pending';
        this.value = undefined;
        this.reason = undefined;
        this.onResolvedCallbacks = [];
        this.onRejectedCallbacks = [];
        console.log('构造函数执行');
        var that = this
        let resolve = (value) => {
          // console.log(value);
          if (this.state === 'pending') {
            this.state = 'fulfilled';
            this.value = value;
            this.onResolvedCallbacks.forEach((fn) => {fn()});
          }
        };
        let reject = (reason) => {
          if (this.state === 'pending') {
            this.state = 'rejected';
            this.reason = reason;
            this.onRejectedCallbacks.forEach((fn) => fn());
          }
        };
        try {
          executor(resolve, reject);
        } catch (err) {
          reject(err);
        }
      }
      // then肯定是前一个promise对象调用
      then(onFulfilled, onRejected) {
        onFulfilled =
          typeof onFulfilled === 'function' ? onFulfilled : (value) => value;
        onRejected =
          typeof onRejected === 'function'
            ? onRejected
            : (err) => {
                throw err;
              };
        let promise2 = new Promise((resolve, reject) => {
          if (this.state === 'fulfilled') {
            setTimeout(() => {
              try {
                let x = onFulfilled(this.value);
                x instanceof Promise ? x.then(resolve, reject) : resolve(x);
                console.log('resolve',that === this);
              } catch (e) {
                reject(e);
              }
            }, 0);
          }
          if (this.state === 'rejected') {
            setTimeout(() => {
              try {
                let x = onRejected(this.reason);
                // resolvePromise(promise2, x, resolve, reject);
                x instanceof Promise ? x.then(resolve, reject) : resolve(x);
              } catch (e) {
                reject(e);
              }
            }, 0);
          }
          if (this.state === 'pending') {
            this.onResolvedCallbacks.push(() => {
              setTimeout(() => {
                try {
                  let x = onFulfilled(this.value);
                  // console.log(this.value,'thisvalue');
                  x instanceof Promise ? x.then(resolve, reject) : resolve(x);
                } catch (e) {
                  reject(e);
                }
              }, 0);
            });
            this.onRejectedCallbacks.push(() => {
              setTimeout(() => {
                try {
                  let x = onRejected(this.reason);
                  // resolvePromise(promise2, x, resolve, reject);
                  x instanceof Promise ? x.then(resolve, reject) : resolve(x);
                } catch (e) {
                  reject(e);
                }
              }, 0);
            });
          }
        });
        // console.log('this',this.state,this.onResolvedCallbacks);
        return promise2;
      }
      catch(fn) {
        return this.then(null, fn);
      }
    }
    function resolvePromise(promise2, x, resolve, reject) {
      if (x === promise2) {
        return reject(new TypeError('Chaining cycle detected for promise'));
      }
      let called;
      if (x != null && (typeof x === 'object' || typeof x === 'function')) {
        try {
          let then = x.then;
          if (typeof then === 'function') {
            then.call(
              x,
              (y) => {
                if (called) return;
                called = true;
                resolvePromise(promise2, y, resolve, reject);
              },
              (err) => {
                if (called) return;
                called = true;
                reject(err);
              }
            );
          } else {
            resolve(x);
          }
        } catch (e) {
          if (called) return;
          called = true;
          reject(e);
        }
      } else {
        resolve(x);
      }
    }
    //resolve方法
    Promise.resolve = function(val) {
      return new Promise((resolve, reject) => {
        resolve(val);
      });
    };
    //reject方法
    Promise.reject = function(val) {
      return new Promise((resolve, reject) => {
        reject(val);
      });
    };
    //race方法
    Promise.race = function(promises) {
      return new Promise((resolve, reject) => {
        for (let i = 0; i < promises.length; i++) {
          promises[i].then(resolve, reject);
        }
      });
    };
    //all方法(获取所有的promise,都执行then,把结果放到数组,一起返回)
    Promise.all = function(promises) {
      let arr = [];
      let i = 0;
      function processData(index, data, resolve) {
      //  index是为了保证多个promise执行产生的结果顺序与原promise一致
        arr[index] = data;
        i++;    // 通过一个闭包,变量i记录是否所有promise已完成
        if (i == promises.length) {
          resolve(arr);
        }
      }
      return new Promise((resolve, reject) => {
        for (let i = 0; i < promises.length; i++) {
          promises[i].then((data) => {
            processData(i, data, resolve);
          }, reject);
        }
      });
    };
    
posted @ 2020-10-18 20:02  365/24/60  阅读(189)  评论(0编辑  收藏  举报