使用事务时节点mysql异步等待问题

时间:2019-09-10 07:28:02

标签: javascript node.js promise async-await node-mysql

我正在用事务编写mysql查询,但是它不等待完成,甚至在函数执行之前就返回结果。

有人可以帮助我知道如何使函数等待响应吗?

调用函数是这样的:

deductUserPoint = await helper.deductUserPoint2(data)
console.log('===============================================')
  console.log(deductUserPoint)
  if (deductUserPoint.isError === true) {
    let error = {}
    error.isError = true
    error.message = 'Unable to deduct amount'
    error.error = deductUserPoint.error
    res.status(200).json(error)
  } else {
    res.status(200).json({ 'isError': false, 'message': 'success' })
  }

我总是以deductUserPoint的身份获得undefined,因为它不等待deductUserPoint2return response

deductUserPoint2如下:

async deductUserPoint2(params) {
    try {
      this.db.connection.getConnection(function(err, conn) {
        console.log('1111111111')
        conn.beginTransaction(function(err) {
        if (err) {
          throw err 
        }
        console.log(params)

        console.log('2222222222')
        conn.query('SELECT id, `expert_id`, user_id, status FROM `call` WHERE `id` = ?', [params.callId], function (error, callInfo, fields) {
          if (error) {
            return conn.rollback(function() {
              throw error
            })
          }

          console.log('33333333')
          let callLength = null
          if (params.callMinute === 'entire_day') {
            callLength = 'entire_day'
          } else {
            const callMinutes = Math.round(params.callMinute)
            if (callMinutes <= 30) {
              callLength = '30_min'
            } else if (callMinutes >= 31 && callMinutes <= 60) {
              callLength = '60_min'
            } else if (callMinutes >= 61 && callMinutes <= 90) {
              callLength = '90_min'
            } else if (callMinutes >= 91) {
              callLength = '120_min'
            }
          }
          console.log('4444444444')
          conn.query('SELECT `amount` FROM `expert_charges` WHERE `status` = "active" AND `call_length` = ? AND `expert_id` = ?', [callLength, callInfo[0].expert_id], function (error, points, fields) {
            if (error) {
              return conn.rollback(function() {
                throw error
              })
            }
            console.log('555555555555')
            let data = {
              fromUserId: callInfo[0].user_id,
              fromUserType: 'user',
              to_user_id: 0,
              to_user_type: null,
              category: 'call',
              type: 'debited',
              callId: params.callId,
              amount: points[0].amount,
              note: params.note,
              point: points[0].amount,
              current_balance_point: 0
            }

            let input = Object.values(data)

            conn.query('INSERT INTO wallet (`from_user_id`, `from_user_type`, `to_user_id`, `to_user_type`, `category`, `type`, `call_id`, `amount`, `note`, `point`, `current_balance_point`) VALUES ?', [[input]], function (error, wallet, fields) {
              if (error) {
                return conn.rollback(function() {
                  throw error
                })
              }
              console.log('666666666666')
              conn.query('UPDATE user SET total_points = total_points - ? WHERE id = ?', [points[0].amount, callInfo[0].user_id], function (error, updateUserPoint, fields) {
                if (error) {
                  return conn.rollback(function() {
                    throw error
                  })
                }
                console.log('7777777777')
                conn.commit(function(err) {
                  if (err) {
                    return conn.rollback(function() {
                      throw err
                    })
                  }
                  console.log('888888888')
                  return {
                    "isError": false,
                    "status": "success"
                  }
                })

                })
              })
          })
        })     
      })
    })

    } catch (error) {
      console.log(error)
      return {
        "isError": true,
        "error": error.toString()
      }
    }

它显示的错误是:

undefined
(node:4197) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'isError' of undefined
    at router.post (/Users/msmexmac/node/msmex-backend/msmex-api/api/wallet.js:120:23)
    at process._tickCallback (internal/process/next_tick.js:68:7)
(node:4197) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:4197) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
1111111111
{ callId: 5, note: 'Deduction for call', callMinute: 25 }
2222222222
33333333
4444444444
555555555555
666666666666
7777777777
888888888

1 个答案:

答案 0 :(得分:0)

您不能使用这样的异步函数,必须返回一个Promise才能等待回调。您的函数将必须像这样结束:

function deductUserPoint2(params) {
    return new Promise(function (resolve, reject) {
        try {
            this.db.connection.getConnection(function (err, conn) {
                console.log('1111111111')
                conn.beginTransaction(function (err) {
                    if (err) {
                        return reject(err)
                    }
                    console.log(params)

                    console.log('2222222222')
                    conn.query('SELECT id, `expert_id`, user_id, status FROM `call` WHERE `id` = ?', [params.callId], function (error, callInfo, fields) {
                        if (error) {
                            return conn.rollback(function () {
                                return reject(error)
                            })
                        }

                        console.log('33333333')
                        let callLength = null
                        if (params.callMinute === 'entire_day') {
                            callLength = 'entire_day'
                        } else {
                            const callMinutes = Math.round(params.callMinute)
                            if (callMinutes <= 30) {
                                callLength = '30_min'
                            } else if (callMinutes >= 31 && callMinutes <= 60) {
                                callLength = '60_min'
                            } else if (callMinutes >= 61 && callMinutes <= 90) {
                                callLength = '90_min'
                            } else if (callMinutes >= 91) {
                                callLength = '120_min'
                            }
                        }
                        console.log('4444444444')
                        conn.query('SELECT `amount` FROM `expert_charges` WHERE `status` = "active" AND `call_length` = ? AND `expert_id` = ?', [callLength, callInfo[0].expert_id], function (error, points, fields) {
                            if (error) {
                                return conn.rollback(function () {
                                    return reject(error)
                                })
                            }
                            console.log('555555555555')
                            let data = {
                                fromUserId: callInfo[0].user_id,
                                fromUserType: 'user',
                                to_user_id: 0,
                                to_user_type: null,
                                category: 'call',
                                type: 'debited',
                                callId: params.callId,
                                amount: points[0].amount,
                                note: params.note,
                                point: points[0].amount,
                                current_balance_point: 0
                            }

                            let input = Object.values(data)

                            conn.query('INSERT INTO wallet (`from_user_id`, `from_user_type`, `to_user_id`, `to_user_type`, `category`, `type`, `call_id`, `amount`, `note`, `point`, `current_balance_point`) VALUES ?', [[input]], function (error, wallet, fields) {
                                if (error) {
                                    return conn.rollback(function () {
                                        return reject(error)
                                    })
                                }
                                console.log('666666666666')
                                conn.query('UPDATE user SET total_points = total_points - ? WHERE id = ?', [points[0].amount, callInfo[0].user_id], function (error, updateUserPoint, fields) {
                                    if (error) {
                                        return conn.rollback(function () {
                                            return reject(error)
                                        })
                                    }
                                    console.log('7777777777')
                                    conn.commit(function (err) {
                                        if (err) {
                                            return conn.rollback(function () {
                                                return reject(err)
                                            })
                                        }
                                        console.log('888888888')
                                        return resolve({
                                            "isError": false,
                                            "status": "success"
                                        })
                                    })

                                })
                            })
                        })
                    })
                })
            })

        } catch (error) {
            console.log(error)
            return resolve({
                "isError": true,
                "error": error.toString()
            })
        }
    })
}

然后,您使用reject(err)代替throw err,用resolve(value)代替return value

另一种方法是按照建议的https://jsfiddle.net/richardmarais/Lwpygd17/1/使用utils.promisify