【问题标题】:Async function with both sync and async code具有同步和异步代码的异步功能
【发布时间】:2018-04-18 12:57:05
【问题描述】:

我有一个返回 true 或 false 的异步函数。它看起来像以下一个:

class User {
  async canManageGroup(group) {
    if (typeof group === 'number') {
      // group - id
      group = await getGroupById(group)
    } // else group is already loaded from DB

    return this.id === group.manager.id
  }
}

如果group参数是组的ID,那么函数将对DB进行异步调用,所以函数canManageGroup将异步执行。但是如果group 参数是组模型,那么函数只会调用return this.id === group.manager.id 或者它会同步执行。以这种方式编写代码是一种好习惯吗?或者我应该将同步代码转换为异步代码?

function makeAsync(cb) {
  return new Promise(resolve => setImmediate(() => resolve(cb())))
}

class User {
  async canManageGroup(group) {
    if (typeof group === 'number') {
      // group - id
      group = await getGroupById(group)
    } // else group is already loaded from DB

    return await makeAsync(() => this.id === group.manager.id)
  }
}

【问题讨论】:

  • 不,不要做第二个......这在async函数中是多余的
  • 可能的解决方案:让canManageGroup 总是期望一个组(从不是组 ID);如果调用者只有一个组ID,那么他们可以调用canManageGroup(await getGroupById(groupId))

标签: javascript async-await


【解决方案1】:

您可以毫无问题地使用第一个示例。

当您使用async 时,您的函数将返回Promise。如果您的代码是sync,则返回的promise 的状态将为resolved,并且可以安全地在其上运行任何与promise 相关的代码(thencatch 等)。

例如:

async function truePromise() {
  return true;
}

truePromise().then(function(value){
  console.log("Promise value:", value);
});

正常工作:)

你应该这样做吗?

是的。由于async 关键字,它可以正常工作。

不得执行以下操作:

function dontDoIt(doSync) {
  if (doSync) return false;
  return Promise.resolve(false)
}

为什么?因为:

  • 如果doSync 是真的,它将返回假(即布尔值)
  • 如果doSync 是假的,它将返回一个Promise,该Promise 将解析为假。

这是一个巨大的差异。

为什么?

您的函数有时会返回一个 Promise,有时会返回一个布尔值。不一致。

  • doSync(true) 是布尔值,不能使用 await 或 .then。
  • doSync(false) 是 Promise,可以使用 await 和 then。

【讨论】:

  • 我知道这段代码会起作用。但是在异步函数中编写同步代码好吗?根据这篇帖子stackoverflow.com/a/22286961/9363390我不应该在异步函数中编写同步代码
  • 更新了我的答案。 TLDR;如果你使用async 关键字,没关系。如果不这样做,您可能会遇到不一致的问题。顺便说一句,当您使用 async 关键字时,链接答案的作者指出的一致性问题不是问题。
【解决方案2】:

根据您对问题How do you create custom asynchronous functions in node.js?的答案而关注的答案之一的评论

问题是,这个函数是不一致的:有时它是异步的,有时不是。假设您有这样的消费者:

在像 nodejs 这样的 js 环境中,可以异步执行的 callback 是一种常见的做法,无论实际代码是否真的是异步的,都应该始终将其称为异步。

所以你想知道下面的代码是否会破坏这种常见的做法。

async function doSomething() {
  return true
}

doSomething()
.then(res => {
   console.log(res)
})

情况并非如此,因为这里处理的是 Promise,并且允许立即解析 Promise,上面的代码基本上和你写的一样:

Promise.resolve(true)
.then(res => {
   console.log(res)
})

在链接部分(then/catch)确保了异步行为,您传递给then/catch的回调将被称为异步:

async function doSomething() {
  return true
}

console.log('before');

doSomething()
  .then(res => {
    console.log('with in callback')
  })

console.log('after');

如您所见,日志的顺序是:

之前
之后
with in 回调

所以这与 常规异步回调函数的顺序相同。

【讨论】:

    【解决方案3】:

    第一个是正确的。如果不需要,则无需强制任何内容异步。上下文切换不是免费的,所以如果它不需要等待任何事情完成,就不要尝试去做。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-25
      相关资源
      最近更新 更多