关闭

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

时间: 2018-04-16阅读: 1407标签: 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吗

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

Js Promise的并行和串行

Promise.all是所有的Promise执行完毕后(reject|resolve)返回一个Promise对象。最近在开发一个项目中,需要等接口拿到全部数据后刷新页面,取消loding效果

JS中Promise.reject()

es6中Promise.reject(reason)方法返回一个带有拒绝原因reason参数的Promise对象。该方法也会返回一个新的 Promise 实例,该实例的状态为rejected。

ES6之Promise

所谓的 promise,简单的来说就是一个容器,里面保存着某个未来才会结束的事件(也就是我们的异步操作)的结果。从语法上面来说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。

关于javascript中的promise的用法和注意事项

promise是javascript中标准的内置对象,用于表示一个异步操作的最终状态(是失败还是成功完成)及其结果值。它让你能够把异步操作最终成功或者失败的原因和响应的处理程序相关联

Promise.resolve()详解

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

关于 Promise 的 9 个提示

你可以在 .then 里面 return 一个 Promise,每次执行 .then 的时候都会自动创建一个新的 Promise,对调用者来说,Promise 的 resolved/rejected 状态是唯一的,Promise 构造函数不是解决方案,使用 Promise.resolve

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

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

手写Promise

可以看到new了一个Promise,里面有一个回调函数,回调函数里有2个参数,分别又是另外2个函数。其实里面很多也都是回调函数的封装调用。

把 Node.js中的回调转换为Promise

在 ES6 中引入了 Promise 作为这些问题的解决方案。最后通过引入 async/await 关键字来提供更好的体验并提高了可读性。即使有了新的方法,但是仍然有许多使用回调的原生模块和库

点击更多...

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