跳转到主要内容
模块 7 · 第 4 课(共 4)课程中的28/32~12 min
模块课程(4/4)

异步代码中的错误

异步操作失败的方式与同步操作不同:错误不会立即到达, 当 Promise 进入 rejected 状态时,它会“稍后”到达。让我们看看两个主要工具。

try/catch 与 await

当您将 await 放在失败的 Promise 之前时,该错误将被 重新抛出 作为 正常异常:您可以使用 try/catch 捕获它。

JS
async function safeRead() {
  try {
    const r = await fetch('/api/cose');
    if (!r.ok) throw new Error('HTTP ' + r.status);
    return await r.json();
  } catch (err) {
    console.error('network error:', err.message);
    return null;
  }
}

这是最具可读性的模式:线性地编写“快乐路径”,并在单个块中处理所有内容。

Promise 上的 .catch

链式风格:

JS
fetch('/api/cose')
  .then((r) => r.json())
  .then((data) => console.log(data))
  .catch((err) => console.error(err));

.catch 捕获沿前面的链抛出的任何错误。

Promise.all 在第一次拒绝时失败

JS
const ps = [Promise.resolve(1), Promise.reject(new Error('no')), Promise.resolve(3)];
try {
  const r = await Promise.all(ps);
} catch (err) {
  console.log(err.message); // 'no'
}

其他 Promise 继续在后台运行,但 Promise.all “解决”第一个错误。 如果您想要所有结果(包括失败),请使用 Promise.allSettled:

JS
const outcomes = await Promise.allSettled(ps);
// [{ status: 'fulfilled', value: 1 },
//  { status: 'rejected', reason: Error('no') },
//  { status: 'fulfilled', value: 3 }]

尝试一下

锻炼#js.m7.l4.e1
尝试:0加载中...

定义异步`readOrFallback(p,fallback)`:尝试等待Promise p;如果被拒绝,则返回后备。

正在加载编辑器...
显示提示

尝试{返回等待p; } catch { 返回后备; }

3 次尝试后可用的解决方案

复习练习

锻炼#js.m7.l4.e2
尝试:0加载中...

定义异步 `allOrNothing(promises)`:使用 Promise.all。如果至少有一个失败,则返回空数组 []。否则返回值。

正在加载编辑器...
显示提示

尝试 { 返回等待 Promise.all(promises); } 捕获{ 返回[]; }

3 次尝试后可用的解决方案