如果满足特定条件,如何跳过承诺链中的步骤而不使代码复杂化?
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?
});
}
这取决于您想要发生什么。如果您想在
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 回调而不是
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) => {
// ...
}
);
}
});
}