Promise 基本原理 & 异步

author: 陈家宾
email: 617822642@qq.com
date: 2018/2/23

Promise 基础完成

var PENDING = 0;
var FULFILLED = 1;
var REJECTED = 2;

function Promise(fn) {
    var state = PENDING;
    var value = null;
    var handlers = [];

    doResolve(fn, resolve, reject)

    function fulfill(result) {}
    // state=fulfilled, value=result

    function reject(error) {}
    // state=rejected, value=error

    function resolve(result) {}
    // if then in result(result 是个 promise), 实行 doResolve
    // else 实行 fulfill
    
    function doResolve(fn, onFulfilled, onRejected) {}
    // 给 fn 传入 resolve 和 reject 函数
    // resolve 函数,实行 onFulfilled
    // reject 函数,实行 onRejected
    
    function handle(handler) {}
    // if PENDING, push handler
    // if FULFILLED, 实行 handler 中的 onFulfilled 函数
    // if REJECTED, 实行 handler 中的 onRejected 函数
    
    this.done = function (onFulfilled, onRejected) {}
    // 异步(setTimeout 0)实行 handler({onFulfilled, onRejected})
    
    this.then = function (onFulfilled, onRejected) {
        var self = this
        return new Promise((resolve,reject)=>{
            return self.done(result=>{
                if onFulfilled
                    return resolve(onFulfilled(result))
                else 
                    return resolve(result)
            }, err=>{
                if onRejected
                    return resolve(onRejected(err))
                else
                    return reject(err)
            })
        })
    }
}

基础语法

new Promsie((resolve, reject) => {
    // function1()
    resolve()
}).then(() => {
    // function2()
})

这里 function1 同步实行,function2 异步实行

Promise 本轮轮回 & 次轮轮回

原本认为 Promise 的内容就到此为止了,厥后看到了阮先生的一篇博客,内里说异步分两种,what?!!

异步使命能够分红两种。

  • 追加在本轮轮回的异步使命
  • 追加在次轮轮回的异步使命

Node 划定,process.nextTickPromise的回调函数,追加在本轮轮回,即同步使命一旦实行完成,就最先实行它们。而setTimeoutsetIntervalsetImmediate的回调函数,追加在次轮轮回。

异步分两种已让我大开眼界,但在我的学问天下里,Promise 不是用 setTimeout 来完成异步的吗,为何 Promise 和 setTimeout 还分属于差异的异步范例里呢?

OK,立时找一下 Promise 的 polyfill 原码

if (isNode) {
  scheduleFlush = useNextTick();
} else if (BrowserMutationObserver) { // BrowserMutationObserver = window.MutationObserver
  scheduleFlush = useMutationObserver();
} else if (isWorker) { // typeof Uint8ClampedArray !== 'undefined' && typeof importScripts !== 'undefined' && typeof MessageChannel !== 'undefined'
  scheduleFlush = useMessageChannel();
} else if (browserWindow === undefined && typeof require === 'function') { // browserWindow = typeof window !== 'undefined' ? window : undefined
  scheduleFlush = attemptVertx();
} else {
  scheduleFlush = useSetTimeout();
}

本来 Promise 的异步不单单议只是 setTimeout,这里会依据差异环境来采纳差异的完成体式格局,浏览器中重要用了 MutationObserver 和 setTimeout

我们先来看一下 MutationObserver 的兼容性(下图参考 https://developer.mozilla.org…

《Promise 基本原理 & 异步》

《Promise 基本原理 & 异步》

由上图可知,运用 polyfill,从以上版本最先,Promise 是由 MutationObserver 完成的本轮轮回的异步使命,低于以上版本的,则是由 setTimeout 完成的次轮轮回的异步使命(本轮轮回在次轮轮回之前实行)。其带来的详细差异以下:

// ie11
setTimeout(function () {console.log(1)});
Promise.resolve().then(function () {
  console.log(2);
});
// 输出效果为 2 1

// ie10
setTimeout(function () {console.log(1)});
Promise.resolve().then(function () {
  console.log(2);
});
// 输出效果为 1 2

其他

shim VS polyfill

  • shim,给浏览器带来新 API 的库,如 jQuery
  • polyfill 则是针对浏览器的一种补丁,一种补充,使其行动与其他浏览器保持一致,如 promise-polyfill

单词 polyfill 的由来:

Polyfilla is a UK product known as Spackling Paste in the US. With that in mind: think of the browsers as a wall with cracks in it. These [polyfills] help smooth out the cracks and give us a nice smooth wall of browsers to work with.——Remy Sharp

参考资料

  1. 《Node 定时器详解》,阮一峰,2018年2月23日,http://www.ruanyifeng.com/blo…
  2. What is the difference between a shim and a polyfill? ,stack overflow,closed at Jul 30 ’15,https://stackoverflow.com/que…
  3. 《Speaking JavaScript》,Axel Rauschmayer,March 2014,http://speakingjs.com/es5/ch3…
    原文作者:henry_chen
    原文地址: https://segmentfault.com/a/1190000013335919
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞