博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[翻译]简单的实现一个Promise
阅读量:6481 次
发布时间:2019-06-23

本文共 6122 字,大约阅读时间需要 20 分钟。

        英文原文为:

1. 状态机

        因为 promise 对象是一个状态机,所以我们首先应该定义将要用到的状态。

var PENDING = 0;var FULFILLED = 1;VAR REJECTED = 2;function Promise () {    // 可以存储这些状态,PENDING、FULFILLED 或 REJECTED    var state = PENDING;    // 当为 FULFILLED 或 REJECTED 状态时,存储值或错误信息    var value = null;    // 存储被 .then 或 .done 方法调用的成功和失败的处理函数    var handlers = [];}

2. 转换

        接着,让我们来考虑一下两个可能发生的重要转换,fulfilling 和 rejecting:

var PENDING = 0;var FULFILLED = 1;var REJECTED = 2;function Promise () {    // 可以存储这些状态,PENDING、FULFILLED 或 REJECTED    var state = PENDING;    // 当为 FULFILLED 或 REJECTED 状态时,存储值或错误信息    var value = null;    // 存储被 .then 或 .done 方法调用的成功和失败的处理函数    var handlers = [];    function fulfill (result) {        state = FULFILLED;        value = result;    }    function reject (error) {        state = REJECTED;        value = error;    }}

        这给了我们基础的低层转换,我们现在来考虑更高层的转换 resolve。

var PENDING = 0;var FULFILLED = 1;var REJECTED = 2;function Promise () {    // 可以存储这些状态,PENDING、FULFILLED 或 REJECTED    var state = PENDING;    // 当为 FULFILLED 或 REJECTED 状态时,存储值或错误信息    var value = null;    // 存储被 .then 或 .done 方法调用的成功和失败的处理函数    var handlers = [];    function fulfill (result) {        state = FULFILLED;        value = result;    }    function reject (error) {        state = REJECTED;        value = error;    }    function resolve (result) {        try {            var then = getThen(result);            if (then) {                doResolve(then.bind(result), resolve, reject);                return;            }            fulfill(result);        } catch (e) {            reject(e);        }    }}

        注意 resolve 如何判断接收的是一个 promise 对象还是一个基本值(plain value),如果是一个 promise 对象,如何等待他完成。

/**  * 检查值是否是一个 Promise 对象, 如果他是, * 返回这个 Promise 对象的‘then’方法。 * * @param {Promise|Any} value * @return {Function|Null}*/function getThen (value) {    var t = typeof value;    if (value && (t === 'object' || t === 'function')) {        var then = value.then        if (typeof then === 'function') {            return then;        }    }    return null;}/** * 潜在的解析函数,以确保 onFulfilled 和 onRejected 只执行其中的一个 */function doResolve (fn, onFulfilled, onRejected) {    var done = false;    try {        fn (function (value) {            if (done) return            done = true            onFulfilled(value);        }, function (reason) {            if (done) return            done = true            onRejected(reason);        })    } catch (ex) {        if (done) return        done = true        onRejected(ex);    }}

3. 构造

        我们现在有了完整的内部状态机,但我们还没有暴露出解决承诺(resolving promise)或观察它的方法。让我们从增加一个解决 promise 的方法开始。

var PENDING = 0;var FULFILLED = 1;VAR REJECTED = 2;function Promise () {    // 可以存储这些状态,PENDING、FULFILLED 或 REJECTED    var state = PENDING;    // 当为 FULFILLED 或 REJECTED 状态时,存储值或错误信息    var value = null;    // 存储被 .then 或 .done 方法调用的成功和失败的处理函数    var handlers = [];    function fulfill (result) {        state = FULFILLED;        value = result;    }    function reject (error) {        state = REJECTED;        value = error;    }    function resolve (result) {        try {            var then = getThen(result);            if (then) {                doResolve(then.bind(result), resolve, reject);                return;            }            fulfill(result);        } catch (e) {            reject(e);        }    }    doResolve(fn, resolve, reject);}

        你可以看到,我们复用了 doResolve,因为我们有另一个不可信的解析。fn 允许多次调用 resolve 和 reject,甚至抛出异常。我们要确保 promise 只 resolve 一次或 reject 一次,然后再也不会过渡到另一个状态。

4. 观察(使用 .done)

        我们现在拥有一个已完成的状态机,但是我们仍没有办法去观察它的变化。我们的最终目的是实现 .then,但是 .done 的语义要简单的多,所以我们首先实现它。

        我们这里的目标是实现 promise.done(onFulfilled, onRejected):

  • 只调用 onFulfilled 或 onRejected 中的一个
  • 它是调用一次
  • 它在下一时刻被调用(例如,在 .done 方法已经返回后)
  • 不管我们在调用之前或之后是否解决了这个问题,它都被调用了。
var PENDING = 0;var FULFILLED = 1;var REJECTED = 2;function Promise (fn) {    // 可以存储这些状态,PENDING、FULFILLED 或 REJECTED    var state = PENDING;    // 当为 FULFILLED 或 REJECTED 状态时,存储值或错误信息    var value = null;    // 存储被 .then 或 .done 方法调用的成功和失败的处理函数    var handlers = [];    function fulfill(result) {        state = FULFILLED;        value = result;        handlers.forEach(handle);        handlers = null;    }    function reject (result) {        state = REJECTED        value = result        handlers.forEach(handle)        handlers = null    }    function resolve (result) {        try {            var then = getThen(result)            if (then) {                doResolve(then, resolve, reject)                return            }            fulfill(result)        } catch (ex) {            reject(ex)        }    }    function handle (handler) {        if (state === PENDING) {            handlers.push(handler);        } else {            if (state === FULFILLED && typeof handlers.onFulfilled === 'function') {                handler.onFulfilled(value);            }            if (state === REJECTED && typeof handlers.onRejected === 'function') {                handler.onRejected(value);            }        }    }    this.done = function (onFulfilled, onRejected) {        // 确保我们总是异步执行的        setTimeout(function () {            handler({                onFulfilled: onFulfilled,                onRejected: onRejected            })        }, 0)    }        doResolve(fn, resolve, reject);}

        当 Promise 被解决或拒绝时,我们要确保去通知 handlers。

5. 观察(使用 .then)

        现在我们已经实现了 .done,我们可以简单的实现 .then 来实现相同的事情,但是在程序中构造一个新的 Promise 对象。

this.then = function (onFulfilled, onRejected) {    var self = this;    return new Promise(function (resolve, reject) {        return self.done(function (result) {            if (typeof onFulfilled === 'function') {                try {                    return resolve(onFulfilled(result));                } catch (ex) {                    return reject(ex);                }            } else {                return resolve(result);            }        }, function (error) {            if (typeof onRejected === 'function') {                try {                    return resolve(onRejected(error));                } catch (ex) {                    return reject(ex);                }            } else {                return reject(error);            }        });    });}

转载于:https://www.cnblogs.com/SyMind/p/8530429.html

你可能感兴趣的文章
<转>Python: __init__.py 用法
查看>>
Linux Curl命令
查看>>
-27979 LoadRunner 错误27979 找不到请求表单 Action.c(73): Error -27979: Requested form not found...
查看>>
[LeetCode] Minimum Depth of Binary Tree
查看>>
,net运行框架
查看>>
Java 中 Emoji 的正则表达式
查看>>
Mixin Network第一届开发者大赛作品介绍- dodice, diceos和Fox.one luckycoin
查看>>
安卓Glide(4.7.1)使用笔记 01 - 引入项目
查看>>
中金易云:为出版社找到下一本《解忧杂货店》
查看>>
Flex布局
查看>>
Material Design之 AppbarLayout 开发实践总结
查看>>
Flutter之MaterialApp使用详解
查看>>
DataBinding最全使用说明
查看>>
原生Js交互之DSBridge
查看>>
Matlab编程之——卷积神经网络CNN代码解析
查看>>
三篇文章了解 TiDB 技术内幕 —— 说计算
查看>>
copy strong weak assign的区别
查看>>
OpenCV 入门
查看>>
css 3D transform变换
查看>>
ele表格合并行之后的selection选中
查看>>