请教:JavaScript Promise中`<..>.get().then().then().catch().finally()`与`<...>.get().then().catch().then().finally()`的执行差异
Key Differences Between These Two Promise Chain Structures
Great question—this gets to the heart of how Promise error handling and chaining works, and the two structures behave very differently when errors are involved. Let’s break them down step by step.
1. <..>.get().then().then().catch().finally()
This structure uses a single catch as a global safety net for all operations that come before it in the chain. Here’s what happens:
- The
catchwill catch any errors (or rejected Promises) from the initialget()call, the firstthen()handler, or the secondthen()handler. - If an error occurs in any of those three steps, the chain will skip all remaining
then()handlers before thecatchand jump straight to error handling. - Once the
catchfinishes executing (assuming it doesn’t throw a new error), thefinally()will run as expected (it always runs, regardless of success or failure).
Example Code
fetch('/api/data') .then(res => { if (!res.ok) throw new Error('Invalid response'); return res.json(); }) .then(data => { if (!data.length) throw new Error('Empty data set'); return processRawData(data); }) .catch(err => { console.error('Something went wrong in fetch or processing:', err); return defaultData; }) .finally(() => { console.log('Request chain finished—cleaning up'); });
In this case:
- If
fetchfails, or the firstthenthrows, or the secondthenthrows, we hit thecatchimmediately, skipping any unexecutedthens.
2. <...>.get().then().catch().then().finally()
Here, the catch only covers errors from the get() call and the first then() handler. The key difference is what happens after the catch:
- If an error occurs in
get()or the firstthen(), we enter thecatch. Once thecatchhandles the error (and returns a resolved Promise, which it does by default unless you throw), the nextthen()will execute regardless of the earlier error. - If
get()and the firstthen()succeed, the chain skips thecatchand moves straight to the nextthen(). - Important: Any errors thrown in the second
then()won’t be caught by thiscatch—you’d need an additionalcatchat the end to handle those.
Example Code
fetch('/api/data') .then(res => { if (!res.ok) throw new Error('Invalid response'); return res.json(); }) .catch(err => { console.error('Fetch or first parse failed:', err); return fallbackData; // Return a default to keep the chain going }) .then(data => { // This runs whether the first part succeeded or failed! console.log('Displaying data:', data); return renderData(data); }) .finally(() => { console.log('Request chain finished—cleaning up'); });
In this case:
- If
fetchfails, we use thecatchto return fallback data, then the nextthen()renders that fallback. - If the first
thensucceeds, we skip thecatchand render the real data. - If
renderDatathrows an error, there’s nocatchto handle it (unless we add one after thisthen).
Core Takeaways
| Aspect | First Structure (then().then().catch()) | Second Structure (then().catch().then()) |
|---|---|---|
| Error Coverage | Catches errors from get(), then1, then2 | Catches errors only from get() and then1 |
| Execution After Error | Skips remaining thens before catch | Runs the next then() after catch handles the error |
| Use Case | General error handling for the entire chain before the catch | Recovering from early errors to continue the chain |
内容的提问来源于stack exchange,提问作者user13041346
相关产品推荐
相关产品推荐

