不能在无服务器 NodeJS 函数中使用 Async/Await

Cannot use Async/Await in a Serverless NodeJS Function

我是使用 NodeJS 的无服务器新手,我正在尝试使用异步函数来散列密码并在数据库中执行一些操作,问题是当我声明异步函数时,我总是会收到此错误:

但是如果我在这里删除 async 关键字:

module.exports.login = async (event, context, callback) => {

该函数运行正常,但我当然无法在函数内使用 promises。

这是一个端点,可以进行 API 调用。

这是我的代码:

'use strict';

require('dotenv').config({ path: './.env' });

const dataBase = require('./utils/db');
const bcrypt = require('bcrypt');

const encryptPassword = async (plainPassword) => {
   const saltRounds = 10;
   const hashedPassword = await bcrypt.hash(plainPassword, saltRounds);
   return hashedPassword;
};

module.exports.login = async (event, context, callback) => {
   context.callbackWaitsForEmptyEventLoop = false;
   const parsedBody = JSON.parse(event.body);
   const connect = dataBase.connectToDatabase();
   const newPassword = await encryptPassword('test');

   console.log(newPassword);

   connect.query('SELECT * FROM users', (error, results, fields) => {
      if (error) {
         console.error(error);
         callback(null, {
            statusCode: 500,
            body: JSON.stringify({
               error: JSON.stringify(error),
               message: 'Internal Server Error Booh!',
            }),
         });
      }
      if (results) {
         callback(null, {
            statusCode: 200,
            body: JSON.stringify({
               error: results,
               message: 'No Error',
            }),
         });
      }
   });
};

这是我的数据库连接和配置:

db.js

const mysql = require('mysql');
const isDev = true;

// Create mySQL Connection
const connectToDatabase = () => {
   const pool = mysql.createPool({
      host: isDev ? process.env.DATABASE_HOST_DEV : process.env.DATABASE_HOST_PROD,
      user: isDev ? process.env.DATABASE_USER_DEV : DATABASE_USER_PROD,
      password: isDev ? process.env.DATABASE_PASSWORD_DEV : DATABASE_PASSWORD_PROD,
      database: isDev ? process.env.DATABASE_DATABASE_DEV : DATABASE_DATABASE_PROD,
      multipleStatements: true,
   });
   return pool;
};

exports.connectToDatabase = connectToDatabase;
exports.mysql = mysql;

我错过了什么?

编辑:

这一切的目的,是因为我正在学习无服务器。

所有这些都将在 AWS Lambda 中结束,其端点使用 API 网关。

因此,当您调用此端点时,您将向 register/login 发送一些参数到应用程序中。

我需要使用async/await,因为如果你注册一个账户,密码需要被散列然后存储到数据库中,或者如果你登录,密码将需要被比较,这两个动作是异步的。

这就是为什么我需要端点是一个异步函数。

编辑 2:

正在阅读此 post:https://github.com/netlify/netlify-dev-plugin/issues/160

正如 Phil 提到的,async 和 callback 不应该一起使用,所以我修改了我的代码,同样的错误:

'use strict';

require('dotenv').config({ path: './.env' });

const dataBase = require('./utils/db');
const bcrypt = require('bcrypt');

const encryptPassword = async (plainPassword) => {
   const saltRounds = 10;
   const hashedPassword = await bcrypt.hash(plainPassword, saltRounds);
   return hashedPassword;
};

module.exports.login = async (event, context, callback) => {
   context.callbackWaitsForEmptyEventLoop = false;
   const parsedBody = JSON.parse(event.body);
   const connect = dataBase.connectToDatabase();
   const newPassword = await encryptPassword('test');

   console.log(newPassword);

   connect.query('SELECT * FROM users', (error, results, fields) => {
      if (error) {
         console.error(error);
         return {
            error: 'some error to test',
         };
      }
      if (results) {
         return {
            body: 'someBody',
         };
      }
   });
};

最终功能代码:

如果有人想知道如何将这些查询作为承诺,这是我的方法,希望它能帮助那些正在努力解决同样问题的人。

'use strict';

require('dotenv').config({ path: './.env' });

const dataBase = require('./utils/db');
const bcrypt = require('bcrypt');

const encryptPassword = async (plainPassword) => {
   const saltRounds = 10;
   const hashedPassword = await bcrypt.hash(plainPassword, saltRounds);
   return hashedPassword;
};

module.exports.login = async (event, context, callback) => {
   context.callbackWaitsForEmptyEventLoop = false;
   const parsedBody = JSON.parse(event.body);
   const connect = dataBase.connectToDatabase();

   const hashedPassword = await encryptPassword('test');

   console.log(hashedPassword);

   return new Promise((resolve, reject) => {
      connect.query('SELECT * FROM users', (error, result) => {
         if (error) {
            reject(
               callback(null, {
                  statusCode: 500,
                  body: JSON.stringify({
                     error: JSON.stringify(error),
                     message: 'Internal Server Error Booh!',
                  }),
               })
            );
         }
         if (result) {
            resolve(
               callback(null, {
                  statusCode: 200,
                  body: JSON.stringify({
                     data: result,
                     message: 'No Error',
                  }),
               })
            );
         }
      });
   });
};

此致。

快速浏览一下 the docs,您似乎不应该将 asynccallback arg 混合。只能使用其中之一,不能同时使用。

您可以迁移到 mysql2 库,这样您就可以使用 promises 或坚持使用现有的并使用 encryptPassword("test").then() 而不是 await

// no async
module.exports.login = (event, context, callback) => {
  // remove this, you don't want it
  // context.callbackWaitsForEmptyEventLoop = false;

  const parsedBody = JSON.parse(event.body);
  const connect = dataBase.connectToDatabase();
  encryptPassword("test").then(newPassword => { // use .then()
    console.log(newPassword);

    // callback APIs are a pain, recommend migrating to mysql2 and use promises
    connect.query('SELECT * FROM users', (error, results, fields) => {
      if (error) {
        console.error(error);
        return callback(null, {
          statusCode: 500,
          body: JSON.stringify({
            error: JSON.stringify(error),
            message: 'Internal Server Error Booh!',
          }),
        });
      }
      callback(null, {
        statusCode: 200,
        body: JSON.stringify({
          error: results, // error?
          message: 'No Error',
        }),
      });
    }
  });
}