资讯专栏INFORMATION COLUMN

Promise 基本原理 & 异步

mtunique / 2061人阅读

摘要:追加在本轮循环的异步任务追加在次轮循环的异步任务规定,和的回调函数,追加在本轮循环,即同步任务一旦执行完成,就开始执行它们。

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...)

由上图可知,使用 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
参考资料

《Node 定时器详解》,阮一峰,2018年2月23日,http://www.ruanyifeng.com/blo...

What is the difference between a shim and a polyfill? ,stack overflow,closed at Jul 30 "15,https://stackoverflow.com/que...

《Speaking JavaScript》,Axel Rauschmayer,March 2014,http://speakingjs.com/es5/ch3...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/107583.html

相关文章

  • ES6&ES7中的异步之async函数

    摘要:更好的语义和分别表示异步和等待,比起和更容易理解。前边声明关键字,表示内部有内部操作,调用函数会返回一个对象。等价于其中函数就是自动执行器。 async函数 定义 async函数其实就是之前说过的Generator的语法糖,用于实现异步操作。它是ES2017的新标准。 读取两个文件: const fs = require(fs) const readFile = function(f...

    dongxiawu 评论0 收藏0
  • js异步从入门到放弃(实践篇) — 常见写法&面试题解析

    摘要:前文该系列下的前几篇文章分别对不同的几种异步方案原理进行解析,本文将介绍一些实际场景和一些常见的面试题。流程调度里比较常见的一种错误是看似串行的写法,可以感受一下这个例子判断以下几种写法的输出结果辨别输出顺序这类题目一般出现在面试题里。 前文 该系列下的前几篇文章分别对不同的几种异步方案原理进行解析,本文将介绍一些实际场景和一些常见的面试题。(积累不太够,后面想到再补) 正文 流程调度...

    Awbeci 评论0 收藏0
  • Promise & Generator——幸福地用同步方法写异步JavaScript

    摘要:在这里看尤雨溪大神的这篇小短文,非常精简扼要地介绍了当前常用的。根据尤雨溪大神的说法,的也只是的语法糖而已。对象有三种状态,,。对象通过和方法来规定异步结束之后的操作正确处理函数错误处理函数。方便进行后续的成功处理或者错误处理。 最近在写一个自己的网站的时候(可以观摩一下~Colors),在无意识中用callback写了一段嵌套了5重回调函数的可怕的代码。回过神来的时候被自己吓了一跳,...

    Harpsichord1207 评论0 收藏0
  • 一文搞懂Vue3中的异步组件defineAsyncComponentAPI的用法

      为了更好的提升用户的体验,我们要缩短加载的时间,要一些组件仅在需要的时候才加载这样极大的节约加载时间,提升用户访问效果。  现在我们可以用Vue3来作为一个实现方法,即defineAsyncComponent,这个方法可以传递两种类型的参数,分别是函数类型和对象类型,接下来我们分别学习。  传递工厂函数作为参数  defineAsyncComponent方法接收一个工厂函数是它的基本用法,这个...

    3403771864 评论0 收藏0
  • 解析关于JavaScript事件循环同步任务与异步任务

      学习一门知识,有些内容必须要提前明白,比如在学习js中同步异步的问题前,需要明白,js是单线程的,为什么它得是单线程的呢?现在先从它应用的场景来说,就是用来让用户与页面进行交互的吧。假如有js是多线程的,那在这个线程里面,用户点击某个按钮会增加一个DOM节点,在另一个线程里面,用户点击这个按钮又会删除一个DOM节点,那么此时js就不知道该听谁的了。这就是为什么会出现同步异步。假设没有异步,那么...

    3403771864 评论0 收藏0

发表评论

0条评论

mtunique

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<