简单模仿实现 Promise 的异步模式

时间: 2018-04-16阅读: 1690标签: Promise

这篇文章是考虑如何自己实现一个简单 Promise,用以理解 Promise。


需求

实现如下要求:

doSomething().then(function(res){ // res 是 doSomething() 的结果
    doSomethingElse(res);
});


Promise 写法

使用原生Promise方法,代码会如下:

function doSomething() {
    var result = 1;
    return new Promise(function (resolve) {
        resolve(result);
    });
}
function doSomethingElse(arg) {
    console.log(arg);
}
doSomething().then(function (res) {
    doSomethingElse(res);  // 输出 1,然后返回结果是一个 Promise 对象,可以继续链式调用 then 方法
});


仿Promise 写法

接下来仿制一下这个 Promise 函数: 
FPromise 是有状态的(Pending、Fulfilled、Rejected)

function FPromise(fn) {
    var status = "Pending"; // 初始状态
    var res = null;

    function handleFulfilled(value) {
        status = "Fulfilled";
        res = value;
    }

    function handleRejected(reason) {
        status = "Rejected";
        res = reason;
    }

    function handle(handler) {
        var callback = null;
        if (status == "Fulfilled") {
            callback = handler.onFulfilled;
        } else if (status == "Rejected") {
            callback = handler.onRejected;
        }

        callback(res);
    }

    this.then = function (onFulfilled, onRejected) {
        handle({
            onFulfilled: onFulfilled,
            onRejected: onRejected
        })

    }

    fn(handleFulfilled, handleRejected);
}


和原生 Promise的调用方法一样,把 Promise 换成 FPromise 如下:

function doSomething() {
    var result = 1;
    return new FPromise(function (resolve) { // 和 Promise 一样调用
        resolve(result);
    });
}
function doSomethingElse(arg) {
    console.log(arg);
}
doSomething().then(function (res) {
    doSomethingElse(res); // 输出 1,但是没有返回结果,无法继续链式调用 then 方法
});


使用 reject 的情况如下:

function doSomething() {
    var result = 2;
    return new FPromise(function (resolve, reject) {
        if (result == 1) {
            resolve(result);
        } else {
            reject("error");
        }
    });
}
doSomething().then(null, function (reason) {
    console.log(reason) // 输出 ‘error’
});


上面的 FPromise 函数无法进行链式调用,需要在 then 方法中再返回一个新的 FPromise,继续修改之

function FPromise(fn) {
    var status = "Pending"; // 初始状态
    var res = null;

    function handleFulfilled(value) {
        status = "Fulfilled";
        res = value;
    }

    function handleRejected(reason) {
        status = "Rejected";
        res = reason;
    }

    function handle(handler) {

        var callback = null;
        if (status == "Fulfilled") {
            callback = handler.onFulfilled;
        } else if (status == "Rejected") {
            callback = handler.onRejected;
        }


        if (callback) {
            var tmp = callback(res);
            if (status == "Fulfilled") { 
                handler.resolve && handler.resolve(tmp); // 第二个 FPromise 里面的参数是第一个 FPromise 执行的结果
            } else if (status == "Rejected") {
                handler.reject && handler.reject(tmp);
            }
        }
    }

    this.then = function (onFulfilled, onRejected) {
        return new FPromise(function (resolve, reject) {
            handle({
                onFulfilled: onFulfilled,
                onRejected: onRejected,
                resolve: resolve, // 相当于下一个promise 的onFulfilled 方法
                reject: reject
            })
        });
    }

    fn(handleFulfilled, handleRejected);
}


链式调用 then 方法如下,

function doSomething() {
    var result = 1;
    return new FPromise(function (resolve) {
        resolve(result);
    });
}
function doSomethingElse(arg) {
    console.log(arg);
}
doSomething().then(function (res) {
    doSomethingElse(res); // 输出 1
    return res;
}).then(function (res) {
    console.log(res + 1); // 输出 2
});


总结

本文实现的方法只能用于参考Promise的原理,还有很多特性没有实现,比如 race,all 方法的实现。一个更好的实现参考https://github.com/LucaslEliane/fake-promise/blob/master/fake-promise.jsMDN 文档中推荐的是 Promise-Polyfill

如何更好的使用Promise可以参考这个文章https://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html

来源:https://blog.csdn.net/YZ0826/article/details/79943278


站长推荐

1.云服务推荐: 国内主流云服务商,各类云产品的最新活动,优惠券领取。地址:阿里云腾讯云华为云

链接: http://www.fly63.com/article/detial/640

Promise.then链式调用顺序

想用Promise异步实现一个递归调用的接口,用来做简单AI的动作序列。发现一开始接触这个then的时候,不是很清楚,参考了网上的一些写法,改成自己的有问题,所以先静下心来研究一下这个调用的顺序问题

Promise不是Callback

这一篇是在实际工程中遇到的一个难得的例子;反映在Node里两种编程范式的设计冲突。这种冲突具有普适性,但本文仅分析问题本质,不探讨更高层次的抽象。

Promise.resolve()详解

Promise.resolve等价于下面的写法,有时需要将现有对象转为 Promise 对象,Promise.resolve方法就起到这个作用。Promise.resolve方法的参数分成四种情况。那么 then 返回的 Promise 将会成为接受状态(resolve)

自己动手实现一个Promise

Promise 对象是一个代理对象,被代理的值在Promise对象创建时可能是未知的。它允许你为异步操作的成功和失败分别绑定相应的处理方法(handlers)。 这让异步方法可以像同步方法那样返回值

剖析Promise内部结构,一步一步实现一个完整的、能通过所有Test case的Promise类

本文写给有一定Promise使用经验的人,如果你还没有使用过Promise,这篇文章可能不适合你,Promise标准中仅指定了Promise对象的then方法的行为,其它一切我们常见的方法/函数都并没有指定.

为promise增加abort功能

Promise只有三种状态:pending、resolve、reject,一个异步的承诺一旦发出,经历等待(pending)后,最终只能为成功或者失败,中途无法取消(abort)。

理解和使用Promise.all和Promise.race

JavaScript的世界中,所有代码都是单线程执行的。异步执行可以用回调函数实现,但是某些场景并不好用,且不易复用。Promise对象这种链式写法的好处在于,先统一执行逻辑,不关心如何处理结果

如何使用Promise.race() 和 Promise.any() ?

自1996年发布以来,JS 一直在稳步改进。随着ECMAScript版本的许多改进,最近的版本是ES2020。JS 的一个重要更新是Promise,在2015年,它以 ES6 的名义发布。

Promise 中的三兄弟 .all(), .race(), .allSettled()

从ES6 开始,我们大都使用的是 Promise.all()和Promise.race(),Promise.allSettled() 提案已经到第4阶段,因此将会成为ECMAScript 2020的一部分。Promise.all<T>(promises: Iterable<Promise<T>>): Promise<Array<T>>

你真的懂Promise吗

在异步编程中,Promise 扮演了举足轻重的角色,比传统的解决方案(回调函数和事件)更合理和更强大。可能有些小伙伴会有这样的疑问:2020年了,怎么还在谈论Promise?

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!