【问题标题】:NodeJS async function not pausingNodeJS异步功能没有暂停
【发布时间】:2019-01-12 01:14:44
【问题描述】:

我有一个异步函数,它使用 await 调用另一个异步函数,但第一个函数不等待第二个函数完成。

module.exports.checkNewUser = async(uuid) => {
    const getUserQuery = `MATCH (n:USER {uuid:"${uuid}"}) RETURN n;`
    console.log(getUserQuery)
    console.log('1')
    const result = await this.runCypherQuery(getUserQuery)
    console.log('3')
    console.log('results:')
    console.log(JSON.stringify(result, null, indent))
    if(result !== []) throw new Error('user already exists')
    return
}

const request = require('request')
const uri = 'http://localhost:7474/db/data/transaction/commit'

module.exports.runCypherQuery = async(query) => {
    const headers = { Authorization: 'Basic xxx' }
    const json = {statements: [{statement: query, parameters: {}}]}
    //console.log(json)
    request.post({uri: uri, headers: headers, json: json}, (err, res, body) => {
        if(err) throw new Error(err.message)
        //console.log(body)
        const data = body.results[0].data
        console.log('data:')
        console.log(data)
        console.log('2')
        return data
    })
}

终端输出为:

MATCH (n:USER {uuid:"xxx"}) RETURN n;
1
3
results:
undefined
data:
[]
2

【问题讨论】:

  • 可能的重复涉及到使用 JQuery 和回调,我已经检查了这篇文章,干杯。
  • @MarkTyers 问题仍然相同$.ajax( { ..., success: function(response) {...}) 相当于您的request.post({...}, (err, res, body) => {...}) 都使用回调来处理异步结果。解决方案是将该代码包装到一个新的 Promise 中,以将旧的基于回调的异步结果处理转换为基于 Promise 的版本。
  • 与您的问题无关,但您认为result !== [] 应该做什么?这将始终评估为true

标签: javascript node.js promise async-await


【解决方案1】:

您的 runCypherQuery 目前没有返回任何特殊内容。为了await 它,您需要明确指定它返回一个Promise,它在request 完成后解析。只是await 一个async 函数并不意味着async 函数在解析之前等待所有异步操作完成。将基于回调的request 转换为Promise 并返回该Promise,以便它可以正确地awaited:

module.exports.runCypherQuery = (query) => {
  const headers = { Authorization: 'Basic xxx' }
  const json = {statements: [{statement: query, parameters: {}}]}
  return new Promise((resolve, reject) => {
    request.post({uri: uri, headers: headers, json: json}, (err, res, body) => {
      if(err) reject(err.message)
      //console.log(body)
      const data = body.results[0].data
      console.log('data:')
      console.log(data)
      console.log('2')
      resolve(data)
    })
  })
}

【讨论】:

  • 异步函数不支持 resolve() 函数。 return 语句解决了隐含的承诺。
  • @MarkTyers return data 不在async 函数中,而是在request.post( 的回调函数中。 request.post 使用 old 回调样式来处理异步响应,因此您需要将其包装到自己的 Promise 中,该 Promise 确实具有 resolve 参数。或者您使用了基于承诺的request 变体,例如request-promiserequest-promise-native
  • if(err) throw new Error(err.message) 的等效项是 if(err) reject(new Error(err.message))。我个人会使用if(err) reject(err) 重新抛出错误,因为它会有更好的错误堆栈跟踪,但这取决于 OP。
  • 感谢帮助我解决问题的建议,但是我不能接受这个解决方案,因为代码是答案无效。
  • @MarkTyers 你能解释一下答案中的代码到底有什么问题吗?谢谢
【解决方案2】:

为了完整起见并根据@CertainPerformance 给出的建议,此版本在异步函数中使用request-promise 包。

const rp = require('request-promise')
const uri = 'http://localhost:7474/db/data/transaction/commit'

module.exports.runQuery = async(query) => {
    const headers = { Authorization: 'Basic xxx' }
    const json = {statements: [{statement: query, parameters: {}}]}
    //console.log(json)
    const body = await rp.post({uri: uri, headers: headers, json: json})
    return body.results[0].data
}

【讨论】:

    猜你喜欢
    • 2018-01-03
    • 1970-01-01
    • 2021-08-05
    • 1970-01-01
    • 2021-12-27
    • 2023-03-10
    • 2013-05-01
    • 2022-01-25
    • 2023-03-20
    相关资源
    最近更新 更多