【问题标题】:TypeScript Syntax for Handling Promise Rejection用于处理 Promise Rejection 的 TypeScript 语法
【发布时间】:2021-01-07 15:43:46
【问题描述】:

我知道应该通过错误处理来处理被拒绝的承诺。

但是,我怀疑这段代码不起作用:

public myFunction(): Promise<number>
{
  try {
    return this.doThingAsync(...); //Returns a promise
  } catch (e) {
    return Promise.resolve(7); //Fallback value
  }
}

既然第一个return 立即返回了promise,那么try/catch 是不是没有机会处理promise 被拒绝的情况?我查看了转译的 JavaScript 并没有看到任何特别之处,即使我将函数标记为 async

因此,await 需要 处理被拒绝的承诺以在 TypeScript 中工作而不使用 JavaScript 中较旧的 then/catch 语法?

根据我对 Promise 的理解,我希望以下内容起作用:

public async myFunction(): Promise<number>
{
  try {
    const result = await this.doThingAsync(...);
    return result;
  } catch (e) {
    return 7; //Fallback value
  }
}

【问题讨论】:

  • 当你用 async 注释一个函数时,它会隐式返回一个 Promise。你的函数不是异步的,所以你必须明确地返回一个。你不需要await,只需return Promise.resolve(7);
  • 某事已经存在了一段时间并不意味着应该避免它。您仍在使用return,并且一直存在! TypeScript 是 JavaScript 的超集;这意味着 TypeScript 中总会有 JavaScript 的语法。实际上,此处显示的代码中唯一在 JavaScript (ES2020) 中无效的是 public: Promise&lt;number&gt;
  • “我怀疑这段代码行不通”:你为什么不先测试一下?然后你会发现它工作或不工作,你可以问一些与你实际运行的代码有关的东西。
  • @Sildoreth Rejections 在您使用 await 时会导致异常,是的,但这不是 TypeScript 特有的功能。我倾向于关闭 Difference between return await promise and return promise 的副本
  • Promise rejections in TypeScript result in exceptions and can be handled with try/catch 没有。不,他们没有。 Typescript 是一个静态类型系统。它编译了。它在运行时不存在,因此它不能以与 Javascript 不同的方式“处理 Promises”,事实上它在运行时根本不处理值。这与 Typescript 有任何关系的唯一原因是编译器(正确地)警告您,您认为您从函数返回的内容并不是您实际上的内容 在所有情况下都返回。

标签: typescript promise


【解决方案1】:

既然第一次return立即返回promise,那么try/catch是不是没有机会处理promise被拒绝的情况?

确实,会引发错误的异步部分不会在此函数的执行上下文中运行,因此try 块不适用于该异步代码。

async/await 解决方案将具有该函数执行上下文恢复(这是await 的魔力),然后将在try...catch 上下文中处理错误.但是在正常的函数中并没有发生这样的执行上下文恢复,所以try...catch上下文在出错的那一刻是不存在的。

这是一个示例,承诺在 100 毫秒后被拒绝。第一个函数具有与您开始时相同的模式。它不会看到错误,因此存在“未捕获的承诺拒绝”(堆栈片段没有显示这一点,但它在浏览器控制台中)。

// Helper functions:
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
const delayAndError = ms => delay(ms).then(() => {throw "my error"});

function myFunction() {
  try {
    return delayAndError(100);
  } catch(e) {
    return Promise.resolve(7); // never happens
  }
}

myFunction().then(console.log); // This promise will reject; so no output

基本上有两种方法可以做到这一点。您已经展示了async/await 方式。但是您可以在没有该语法的情况下执行此操作。而不是try...catch 块,链接catch 方法调用:

// Helper functions:
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
const delayAndError = ms => delay(ms).then(() => {throw "my error"});

function myFunction() {
  return delayAndError(100).catch(e => 7);
}

myFunction().then(console.log); // 7

【讨论】:

    【解决方案2】:

    确实,在try/catch 中返回一个承诺将不会处理该承诺的未来拒绝。

    简单地将方法切换到async 也不会奏效。为了正确处理错误/拒绝处理,您需要执行以下操作之一。

    使用await

    等待承诺确保控制在方法终止之前返回到方法,使其有机会处理错误。请注意,这需要将方法/函数标记为async

    public async myFunction(): Promise<number>
    {
      try {
        const result = await this.doThingAsync(...);
        return result;
      } catch (e) {
        return 7; //Fallback value
      }
    }
    

    使用catch

    您也可以在 Promise 上使用 catch 来指定当 Promise 被拒绝时应该执行的代码。请注意,catch 本身会返回一个 promise/thenable。

    public myFunction(): Promise<number>
    {
        return this.doThingAsync(...).catch(() =>
        {
          return 7; //Fallback value
        }
    }
    

    【讨论】:

    • 嗯,为什么要重复1小时前给出的答案?
    • 在发布之前,我已经在写答案了。我现在正在工作,所以我在这和会议之间切换。 :)
    • 当我接到电话时,我已经写好了答案,但没有校对。
    猜你喜欢
    • 1970-01-01
    • 2021-08-08
    • 1970-01-01
    • 1970-01-01
    • 2018-01-11
    • 1970-01-01
    • 2020-09-13
    • 2019-11-10
    • 2018-03-19
    相关资源
    最近更新 更多