【问题标题】:Using Promise with async/await将 Promise 与 async/await 一起使用
【发布时间】:2018-01-14 03:52:35
【问题描述】:

我从 TypeScript 中的 async/await 开始,对此我有几个问题。我编写了这个函数来从 Blob 中获取 ArrayBuffer。

async function readAsArrayBuffer(blob: Blob): Promise<ArrayBuffer> {
    return new Promise<ArrayBuffer>((resolve, reject) => {
        let reader = new FileReader();
        reader.addEventListener('load', e => resolve((<FileReader>e.target).result));
        reader.addEventListener('error', e => reject((<FileReader>e.target).error));
        reader.readAsArrayBuffer(blob);
    });
}

所以...

  1. 在这个函数之前我真的需要async 关键字吗?我想,它什么也没做......
  2. 我应该在 Promise 执行器函数范围内还是在 readAsArrayBuffer 范围级别创建新的 FileReader? (……或者没关系?)
  3. 我写的是嵌套在函数中的两个函数。难道我做错了什么? :-)

【问题讨论】:

    标签: typescript async-await es6-promise


    【解决方案1】:

    在这个函数之前我真的需要 async 关键字吗?我想,它什么也没做......

    不。如果你在函数体中使用await,你只需要async关键字。

    我应该在 Promise 执行器函数范围内还是在 readAsArrayBuffer 范围级别创建新的 FileReader? (……或者没关系?)

    我建议将大部分实际代码保留在 executor 函数中。好处是,如果你有一个 同步 异常(例如,如果 new FileReader() 在构造中是 throw),执行器将捕获它并将其转换为异步承诺拒绝。如果你把它放在执行器函数之外,那么你的函数会抛出一个同步异常。这使用起来会很混乱,因为您必须分别处理同步和异步异常。

    我写的是嵌套在函数中的两个函数。难道我做错了什么? :-)

    没关系。当您围绕非承诺 API 编写承诺包装器时,这是一种非常常见的模式。优点是您现在可以将此包装器与await 一起使用,并避免在代码的其他部分中嵌套函数。 :-)

    【讨论】:

    • @trincot 是的,see MDN: "如果执行器函数中抛出错误,则 promise 被拒绝。执行器的返回值被忽略。" 注意当您从开发控制台运行它时,Chrome 会记录“未捕获(承诺中)我的错误”,但这实际上是因为默认的未捕获承诺拒绝处理程序。尝试在其周围加上 try..catch 以查看与仅 throw "my error" 相比的区别。
    • 确实,你是对的。我在 FireFox 中看到的输出不如在 Chrome 中清晰。
    【解决方案2】:
    1. 在这个函数之前我真的需要 async 关键字吗?我想,它什么也没做......

    不,当函数使用await 关键字时,您只需要async,这将使函数异步执行,而您的函数不是这种情况:它同步执行直到完成。异步部分只是在回调的触发中,不是async关键字的意思。

    1. 我应该在 Promise 执行器函数范围内还是在 readAsArrayBuffer 范围级别创建新的 FileReader? (……或者没关系?)

    最佳做法是在作业所需的最小范围内定义变量。虽然它可以以任何一种方式工作,但你现在拥有它会更好。

    1. 我写的是嵌套在函数中的两个函数。难道我做错了什么? :-)

    没有错。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-05
      • 2019-04-15
      • 2014-06-19
      • 2018-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多