【问题标题】:Can I "promisify" a function by just using async?我可以仅通过使用异步来“承诺”一个功能吗?
【发布时间】:2018-11-12 13:55:33
【问题描述】:

所以我有一个函数应该立即返回一个被拒绝或解决的 Promise,即它基本上是一个我想要“承诺”的同步函数。

在这种情况下我通常会这样做:

func() {
     // some code to check for an error
     if (hasError)
        return Promise.reject(new Error("Failure"));
     }
     return Promise.resolve("Success");
}

现在,随着 ES2017 中“异步”功能的可用性,我似乎也可以这样做:

async func() {
     // some code to check for an error
     if (hasError)
        throw new Error("Failure");
     }
     return "Success";
}

所以我基本上使用async 只是为了“承诺”我的函数,而没有在函数体的任何地方使用await。正如我所看到的,这个变体应该做的完全一样。我是对的,还是有任何我不知道的其他副作用?

我想我更喜欢这种模式,因为它有点短,仅从函数定义就很清楚它是异步的,任何 JavaScript 错误(如类型错误)也会导致拒绝,这使我在出现意外错误时,整体代码的反应更加优雅。

【问题讨论】:

  • “在我看来,这个变种应该做的完全一样。” 正确 “我是对的,还是有任何额外的副作用我不是知道这里吗?” 不,这里没有意外。
  • 贝尔吉:为什么?虽然函数本质上是同步的,但我希望它以异步方式表现。原因是我有一个统一各种存储操作的API。我的一些适配器是异步的(XHR),其中一些不是(localStorage)。但我希望有一个统一的 API,这样无论我使用的适配器是否异步,我都可以随时执行 myStorage.read().then(...) 之类的操作。仍然不是您会接受的用例?
  • ... 所以 API 本身是异步的。现在,主类更容易以相同的方式处理来自任何适配器的结果,即期待一个承诺。我还可以使用 Promise.race 一次从多个来源读取数据,支持缓存(即使使用多个适配器)等。所以我敢说:永远不要说“从不”;)

标签: javascript asynchronous promise ecmascript-2017


【解决方案1】:

每当您声明一个异步函数时,都会创建一个AsyncFunction 对象,根据 MDN,它将返回一个 Promise:

将使用异步函数返回的值解析的 Promise,或因异步函数内抛出未捕获的异常而被拒绝。

所以是的,它使用asyncpromisify 一个函数。

另外,让我们做一些测试;

async function fn(val) {
  console.log(val);
  if (val) {
    return "true";
  }
  throw new Error("false");
}

console.log(Object.getPrototypeOf(fn).constructor)

console.log(fn(true) instanceof Promise);
console.log(Object.getPrototypeOf(fn(true)).constructor)

console.log(fn(false) instanceof Promise);
console.log(Object.getPrototypeOf(fn(false)).constructor)

fn(true).then(val => console.log(val));

fn(false).catch(err => console.log("ERROR"));

【讨论】:

  • 是的,这看起来不错!感谢您的测试。我想从现在开始我会使用这种模式,我喜欢它;)
猜你喜欢
  • 1970-01-01
  • 2021-10-01
  • 1970-01-01
  • 2016-02-27
  • 2019-05-27
  • 2017-05-07
  • 2016-02-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多