javascript技巧

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript技巧 > Promise基本方法实现

关于Promise基本方法的简单实现

作者:编程三昧

Promise大家一定都不陌生了,JavaScript异步流程从最初的Callback,到Promise,到Generator,再到目前使用最多的Async/Await,下面这篇文章主要给大家介绍了关于Promise基本方法的简单实现,需要的朋友可以参考下

前言

Promise 是前端面试和工作中极其常见的一个概念,关于它各种方法的手写实现也很有市场,今天在这里总结一下 Promise 基本方法的简单实现。

catch() 方法

catch 方法是对 then 方法的封装,只用于接收 reject(reason) 中的错误信息。

因为在 then 方法中 onRejected 参数是可不传的,不传的情况下,错误信息会依次往后传递,直到有 onRejected 函数接收为止,因此在写 promise 链式调用的时候, then 方法不传 onRejected 函数,只需要在最末尾加一个 catch() 就可以了,这样在该链条中的 promise 发生的错误都会被最后的 catch 捕获到。

catch(onRejected) {
	return this.then(null, onRejected);
}

done() 方法

catch 在 promise 链式调用的末尾调用,用于捕获链条中的错误信息,但是 catch 方法内部也可能出现错误,所以有些 promise 实现中增加了一个方法 done 。

done 相当于提供了一个不会出错的 catch 方法,并且不再返回一个 promise ,一般用来结束一个 promise 链。

done() {
    this.catch(reason => {
        console.log('done', reason);
        throw reason;
    });
}

finally() 方法

finally 方法用于无论是 resolve 还是 reject , finall y的参数函数都会被执行。

finally(fn) {
    return this.then(value => {
        fn();
        return value;
    }, reason => {
        fn();
        throw reason;
    });
};

Promise.all() 方法

Promise.all 方法接收一个 promise 数组,返回一个新 promise2 ,并发执行数组中的全部 promise ,所有 promise 状态都为 resolved 时, promise2 状态为 resolved 并返回全部 promise 结果,结果顺序和 promise 数组顺序一致。如果有一个 promise 为 rejected 状态,则整个 promise2 进入 rejected 状态。

static all(promiseList) {
    return new Promise((resolve, reject) => {
        const result = [];
        let i = 0;
        for (const p of promiseList) {
            p.then(value => {
                result[i] = value;
                if (result.length === promiseList.length) {
                    resolve(result);
                }
            }, reject);
            i++;
        }
    });
}

Promise.race() 方法

Promise.race 方法接收一个 promise 数组, 返回一个新 promise2 ,顺序执行数组中的 promise ,有一个 promise 状态确定, promise2 状态即确定,并且同这个 promise 的状态一致。

static race(promiseList) {
    return new Promise((resolve, reject) => {
        for (const p of promiseList) {
            p.then((value) => {
                resolve(value);
            }, reject);
        }
    });
}

Promise.resolve() 和 Promise.reject()

Promise.resolve 用来生成一个 rejected 完成态的 promise , Promise.reject 用来生成一个 rejected 失败态的 promise 。

static resolve(value) {
    let promise;

    promise = new Promise((resolve, reject) => {
        this.resolvePromise(promise, value, resolve, reject);
    });

    return promise;
}

static reject(reason) {
    return new Promise((resolve, reject) => {
        reject(reason);
    });
}

附Promise 解决过程

Promise 解决过程是一个抽象的操作,其需输入一个 promise 和一个值,我们表示为 [[Resolve]](promise, x),如果 x 有 then 方法且看上去像一个 Promise ,解决程序即尝试使 promise 接受 x 的状态;否则其用 x 的值来执行 promise 。

这种 thenable 的特性使得 Promise 的实现更具有通用性:只要其暴露出一个遵循 Promise/A+ 协议的 then 方法即可;这同时也使遵循 Promise/A+ 规范的实现可以与那些不太规范但可用的实现能良好共存。

运行 [[Resolve]](promise, x) 需遵循以下步骤:

如果 promise 和 x 指向同一对象,以 TypeError 为据因拒绝执行 promise

如果 x 为 Promise ,则使 promise 接受 x 的状态:

- 如果 x 处于等待态, promise 需保持为等待态直至 x 被执行或拒绝
- 如果 x 处于执行态,用相同的值执行 promise
- 如果 x 处于拒绝态,用相同的据因拒绝 promise

如果 x 为对象或者函数:

- 把 x.then 赋值给 then
- 如果取 x.then 的值时抛出错误 e ,则以 e 为据因拒绝 promise
- 如果 then 是函数,将 x 作为函数的作用域 this 调用之。传递两个回调函数作为参数,第一个参数叫做 resolvePromise ,第二个参数叫做 rejectPromise:
    - 如果 resolvePromise 以值 y 为参数被调用,则运行 [[Resolve]](promise, y)
    - 如果 rejectPromise 以据因 r 为参数被调用,则以据因 r 拒绝 promise
    - 如果 resolvePromise 和 rejectPromise 均被调用,或者被同一参数调用了多次,则优先采用首次调用并忽略剩下的调用
    - 如果调用 then 方法抛出了异常 e:
        - 如果 resolvePromise 或 rejectPromise 已经被调用,则忽略之
        - 否则以 e 为据因拒绝 promise
    - 如果 then 不是函数,以 x 为参数执行 promise
- 如果 x 不为对象或者函数,以 x 为参数执行 promise

如果一个 promise 被一个循环的 thenable 链中的对象解决,而 [[Resolve]](promise, thenable) 的递归性质又使得其被再次调用,根据上述的算法将会陷入无限递归之中。算法虽不强制要求,但也鼓励施者检测这样的递归是否存在,若检测到存在则以一个可识别的 TypeError 为据因来拒绝 promise。

总结

常用的方法基本就这些, Promise 还有很多扩展方法,这里就不一一展示,基本上都是对 then 方法的进一步封装,只要你的 then 方法没有问题,其他方法就都可以依赖 then 方法实现。

到此这篇关于Promise基本方法简单实现的文章就介绍到这了,更多相关Promise基本方法实现内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文