如何巧妙使用JavaScript Promise Chains? [重复]

问题描述 投票:0回答:1

如果满足特定条件,如何跳过承诺链中的步骤而不使代码复杂化?

function fetchData(shouldSkip) {
  fetch('https://api.example.com/step1')
    .then(response => response.json())
    .then(data => {
      if (shouldSkip(data)) {
        // Want to jump to final step. How?
      } else {
        return fetch('https://api.example.com/step2').then(response => response.json());
      }
    })
    .then(finalData => {
      // Need to work with finalData here, but what if there's no step2?
    });
}
javascript promise
1个回答
0
投票

这取决于您想要发生什么。如果您想在

data
返回 true 时将
finalData
用作
shouldSkip
,请从第一个
data
回调中返回
then
。如果您想完全跳过第二个回调,请将其放在第一个回调中。根据您对“使代码复杂化”的定义,您还可以采取几种不同的方法,但这里有几种方法。

在大多数情况下,通过使用

async
函数,承诺链变得更简单,所以首先我将向您展示这一点,然后我将向您展示如何使用显式承诺回调做同样的事情,以防万一您有需要它们的一些原因。 (也就是说,
async
函数现在已得到普遍支持。)

使用
async
功能

这是一个尽可能使用

async
函数 的示例。它仍然是 Promise,但使用语法而不是显式的 Promise 回调函数。

首先让我们确保在

fetch
调用中处理 HTTP 失败,因为
fetch
函数仅在 network 失败时拒绝其承诺,而不是 HTTP 失败(如状态 404 或 500)。 (有关详细信息,请参阅我贫血的旧博客上的我的帖子。)让我们通过编写可重用的包装函数来执行必要的检查来做到这一点:

async function fetchJSON(url, init) {
    const response = fetch(url, init);
    if (!response.ok) {
        throw new Error(`HTTP error ${response.status}`);
    }
    return await response.json();
}

现在我们已经有了,我们可以更新

fetchData

如果您想在

data
返回 true 时将
finalData
用作
shouldSkip

async function fetchData(shouldSkip) {
    const data = await fetchJSON("https://api.example.com/step1");
    const finaldata = shouldSkip(data)
        ? data
        : await fetchJSON("https://api.example.com/step2");
    // Here, `finalData` will be `data` from the previous handler if
    // `shouldSkip` returned `true`, or the data from the second `fetchJSON`
}

如果您想在

shouldSkip
返回 true 时完全跳过第二步:

async function fetchData(shouldSkip) {
    const data = fetchJSON("https://api.example.com/step1");
    if (!shouldSkip(data)) {
        const finalData = await fetchJSON("https://api.example.com/step2");
        // ...
    }
}

使用显式的 Promise 回调

如果由于某种原因您需要使用显式的 Promise 回调而不是

async
函数,则如下所示:

从我们可重复使用的

fetchJSON
开始:

function fetchJSON(url, init) {
    return fetch(url, init).then((response) => {
        if (!response.ok) {
            throw new Error(`HTTP error ${response.status}`);
        }
        return response.json();
    });
}

如果您想在最终处理程序中使用

data
作为
finalData

function fetchData(shouldSkip) {
    // Added a return so the caller can handle promise rejections
    return fetchJSON("https://api.example.com/step1")
        .then((data) => {
            return shouldSkip(data)
                ? data
                : fetchJSON("https://api.example.com/step2");
        })
        .then((finalData) => {
            // Here, `finalData` will be `data` from the previous handler if
            // `shouldSkip` returned `true`, or the data from the second `fetchJSON`
        });
}

如果您想跳过最终处理程序:

function fetchData(shouldSkip) {
    // Added a return so the caller can handle promise rejections
    return fetchJSON("https://api.example.com/step1").then((data) => {
        if (!shouldSkip(data)) {
            return fetchJSON("https://api.example.com/step2").then(
                (finalData) => {
                    // ...
                }
            );
        }
    });
}
© www.soinside.com 2019 - 2024. All rights reserved.