将现有函数声明为异步?

时间:2017-12-20 17:25:46

标签: javascript ecmascript-6 async-await

我使用一个名为setConf的函数进行测试。有时,如果我可以使用它来启动一个承诺链,那真的很方便,有时我只需要它来返回值。

是否可以将现有函数声明为异步?我想做但不起作用的是:

const setConf = (conf) => {
  mainConf = Object.assign(mainConf , conf)
  return mainConf 
}

module.exports.asyncSetConf = async setConf
module.exports.setConf = setConf

我目前有

exports.asyncSetConf = async (conf) => {
  mainConf = Object.assign(mainConf , conf)
  return mainConf 
}

exports.setConf = (conf) => {
  mainConf = Object.assign(mainConf , conf)
  return mainConf 
}

代码是完全相同的,不能重构这个

似乎有点傻

1 个答案:

答案 0 :(得分:4)

首先,使用async关键字声明的函数返回一个promise。因此,您要么希望函数返回承诺,要么不希望。没有使用async关键字声明的函数,有时会返回一个promise,有时则不会。

其次,如果你的函数中没有异步代码,那么它通常会使事情变得更复杂,在异步接口中包装同步操作也不会那么复杂,所以通常没有理由这样做。

第三,如果您只是想有时使用setConf()来启动一个保证链,那么当您想要这样做时,可以用Promise.resolve()包裹它:

Promise.resolve(setConf(...)).then(f).then(g).catch(...)

当然,您不一定需要这样做,因为如果f()是异步的并且返回一个承诺,那么您可以这样做:

f(setConfg(...)).then(g).catch(...)

如果你发现自己经常使用Promise.resolve(setConf(...)),那么你可以为它做一个实用功能:

function setConfPromise(...args) {
    return Promise.resolve(setConf(..args))
}
  

是否可以将现有函数声明为async?

您可以更改其声明,也可以使用其他功能进行包装。您有时无法使用async行为进行动态制作,有时则无法动态制作。你需要两个独立的功能。

你可以像这样包装它:

module.exports.asyncSetConf = function(...args) {
    return Promise.resolve(setConf(...args));
}
module.exports.setConf = setConf

仅供参考,async只应在实际需要时使用。关于其用法的一些注意事项:

  1. 当没有涉及实际的异步代码时,不应该使用async。在同步代码上设置异步接口只会使用比所需更复杂的功能。
  2. 如果要在功能中使用async,请使用await
  3. 当您强制自动返回承诺并使某些例外自动被捕获并变成被拒绝的承诺时,请使用async
  4. 就个人而言,当我想在函数中使用async时,我只会使用await

    您不需要仅使用async来返回承诺。你可以通过回复承诺来实现“老式”的方式。

    使用async不会使任何同步代码突然异步运行(一个常见的新手假设)。它根本不会改变同步代码。它强制返回值为一个承诺,调用者必须使用await.then()来获取值,从而迫使.then()执行“下一次”执行,但是如果函数中的代码都是同步的,它仍然会同步执行 - async不会改变它。