美文网首页
JavaScript `Promise` 全解析

JavaScript `Promise` 全解析

作者: you的日常 | 来源:发表于2021-12-01 17:29 被阅读0次

Promise 是 JavaScript 中的对异步操作最佳的 API 之一。作为 JavaScript 开发人员,需要熟练掌握 Promise 相关的知识。本文就来总结一下这些知识点,先来回顾 JavaScript 过去异步操作的处理方式?然后详细介绍 Promises 对象及相关的方法。

现在先来了解一下 JavaScript 异步概念。

异步回顾

什么是异步?如果在函数返回的时候,调用者还不能获取到预期结果,而是将来通过一定的方式得到(例如回调函数),这函数就是异步。

异步回调

异步回调,就是常见的 callback ,这是过去在 JavaScript 中处理异步操作的常见方式,如 AJAX ,发起一个 HTTP 请求,具体服务器什么时候返回响应数据取决于客户的环境,存在很多不确定因素,这时采用回调函数可以在返回响应数据的时候触发回调函数。

这种方式当有多个请求的情况,后续请求需要等待前面请求的响应数据的时候,就会出现常见的回调地狱。

const asyncMessage = function (message, callback) {
    setTimeout(function () {
        console.log(message);
        callback();
    }, 1000);
};

asyncMessage("title", function () {
    asyncMessage("cate", function () {
        asyncMessage("content", function () {
            console.log("detail");
        });
    });
});

出现回调地狱将会给项目开发带来很多问题:

  • 会导致逻辑混乱,耦合性高,改动一处就会导致全部变动,嵌套多时,BUG 问题难以发现。

  • 不能使用 try...catch 来捕获异常。

  • 不能使用 return 返回真实数据

为了避免回调地狱的出现,后来就有了 Promise 对象。

Promise 的工作方式

promise 对象是一个可以从异步函数同步返回的对象,它将处于 3 种可能的状态之一:

fulfilled 已兑现: onFulfilled() 将被调用,即操作完成(例如,resolve() 被调用)rejected 已拒绝: onRejected() 将被调用,即操作失败(例如,reject() 被调用)pending 待定:初始状态,既没有被兑现,也没有被拒绝

如果一个 promise 没有挂起(它已被解决或拒绝),它就会被解决。有时使用已解决和已解决表示同一件事:不是 pending

promise 一旦确定,就不能再重新确定,再次调用 resolve()reject() 将没有效果。一个已确定的 promise 的具有不可变性。

对于 promise 的状态监控可以使用承诺链,即在 fulfilled 已兑现的状态可以使用 then 方法可以获取已兑现的结果,在rejected 已拒绝状态使用 catch 方法获取拒绝的原因。

const myPromise = new Promise(myExecutorFunc)
    .then(handleFulfilledA)
    .then(handleFulfilledB)
    .then(handleFulfilledC)
    .catch(handleRejectedAny);

看起来比 callback 的方式优雅一点,对于需要发起多次 HTTP 请求才能完整呈现的需求,代码如下:

const getPost = () => fetch("https://jsonplaceholder.typicode.com/posts/1");
const getAuthor = (id) =>
    fetch("https://jsonplaceholder.typicode.com/users/" + id);
const getComment = (id) =>
    fetch("https://jsonplaceholder.typicode.com/users/" + id);

getPost() // #1.fetch post
    .then((postResponse) => postResponse.json()) // #2. get & return post json
    .then((postResponse) =>
        getAuthor(postResponse.id) // #3. fetch author
            .then((authorResponse) =>
                authorResponse
                    .json() // #4 get & return author json
                    .then((authorResponse) =>
                        getComment(postResponse.id) // #5 fetch comment
                            .then((commentResponse) => commentResponse.json()) // #6 get & return comment json
                            .then((commentResponse) => {
                                // #7 time to combine all results
                                return {
                                    postResponse,
                                    authorResponse,
                                    commentResponse,
                                }; // #8 combine & return all reponses
                            })
                    )
            )
            .then((results) => {
                // #9 read all responses
                console.log(results.postResponse);
                console.log(results.authorResponse);
                console.log(results.commentResponse);
            })
    )
    .catch((error) => console.log(error)); // # 10 error handling

上面代码是否有种似曾相识的感觉,原本是为了解决回调地狱,但似乎理想跟现实还是有差距。

于是 ES2021 为 Promise 对象增加新的特征,其中包括:Promise.any()Promise.all()Promise.allSettled()Promise.race()

Promise.any()

Promise.any(promises) 能够并行运行 promise,并解析为 promises 列表中第一个成功解析的 promise 的值。需要注意的是 Promise.any() 方法依然是实验性的,尚未被所有的浏览器完全支持。

下面来看看 Promise.any() 是如何工作的。

1.工作原理

Promise.any() 可用于以并行和竞争方式执行独立的异步操作,以获取任何第一个完成的 promise 的值。

该函数接受一个 promise 数组(通常为一个可迭代对象)作为参数,如下:

const anyPromise = Promise.any(promises);

当输入 promises 中的第一个 promise 被执行完成时,anyPromise 会立即解析为该 promise 的值。

image

可以使用 then 方法提取第一个 promise 的值:

anyPromise.then((firstValue) => {
    firstValue; // 第一个 promise 完成后返回的值
});

也可以使用 async/await 语法:

const firstValue = await anyPromise;
console.log(firstValue); // 第一个 promise 完成后返回的值

Promise.any() 返回的 promise 与任何第一个执行的 promise 一起执行。即使某些 promiserejected,这些 rejections 也将会被忽略。

image

相关文章

网友评论

      本文标题:JavaScript `Promise` 全解析

      本文链接:https://www.haomeiwen.com/subject/vdqqoltx.html