0

我试图在循环中运行 MySQL DELETE 命令,试图删除多个项目。下面是我用 Node.js 编写的 AWS Lambda 代码。

const mysql = require('mysql2');
const errorCodes = require('source/error-codes');
const PropertiesReader = require('properties-reader');

const prop = PropertiesReader('properties.properties');

const con = mysql.createConnection({
    host: prop.get('server.host'),
    user: prop.get("server.username"),
    password: prop.get("server.password"),
    port: prop.get("server.port"),
    database: prop.get("server.dbname")
});


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

    context.callbackWaitsForEmptyEventLoop = false;

    if (event.body == null && event.body == undefined) {
        var response = errorCodes.missing_parameters;
        callback(null, response)
    }
    else {
        let body = JSON.parse(event.body)
        let response="";
        //console.log("body", body);

        for(let i=0;i<body.length;i++)
        {
            
            let idseller_portfolio_item_images = Number(body[i].idseller_portfolio_item_images);   
            console.log(idseller_portfolio_item_images);  

            if (isNaN(idseller_portfolio_item_images)) {
                response = errorCodes.invalid_parameter;
                callback(null, response);
            }
            else {
                // allows for using callbacks as finish/error-handlers
                const sql = "DELETE FROM seller_portfolio_item_images WHERE idseller_portfolio_item_images = ? ";
                await con.execute(sql, [idseller_portfolio_item_images], function (err, result) {
                    if (err) {
                        console.log(err.toString());

                        if (err.toString().indexOf('cannot be null') >= 0) {
                            response = errorCodes.not_null_parameters;
                            callback(null, response);
                        }
                        response = errorCodes.internal_server_error;
                        callback(null, response);

                    }
                    else {
                        response = {
                            "statusCode": 200,
                            "headers": {
                                "Content-Type": "application/json"
                            },
                            "body": JSON.stringify({ status: 1 }),
                            "isBase64Encoded": false
                        };
                        
                    }
                });
            }
        }
        //If there is no error, this response will be sent back after the for loop
        callback(null, response);
    }
};

然而,这只是返回一个空响应,没有记录被删除。

但是如果我删除循环callback(null, response);之后for,记录将被删除。在这种情况下,无论如何都会发回错误,因为没有callback.

我认为这是因为我的代码没有等待 for 循环完成而只是等待callback.

我也试过这个如下。

const mysql = require('mysql2');
const errorCodes = require('source/error-codes');
const PropertiesReader = require('properties-reader');

const prop = PropertiesReader('properties.properties');

const con = mysql.createConnection({
    host: prop.get('server.host'),
    user: prop.get("server.username"),
    password: prop.get("server.password"),
    port: prop.get("server.port"),
    database: prop.get("server.dbname")
});


exports.deleteSellerPortfolioItemImages =  (event, context, callback) => {

    context.callbackWaitsForEmptyEventLoop = false;

    if (event.body == null && event.body == undefined) {
        var response = errorCodes.missing_parameters;
        callback(null, response)
    }
    else {
        let body = JSON.parse(event.body)
        let response="";

        body.forEach(async (element, index)=>{
            let idseller_portfolio_item_images = Number(element.idseller_portfolio_item_images);   
            console.log(idseller_portfolio_item_images);  

            if (isNaN(idseller_portfolio_item_images)) {
                response = errorCodes.invalid_parameter;
                callback(null, response);
            }
            else {
                // allows for using callbacks as finish/error-handlers
                const sql = "DELETE FROM seller_portfolio_item_images WHERE idseller_portfolio_item_images = ? ";
                await con.execute(sql, [idseller_portfolio_item_images], function (err, result) {
                    if (err) {
                        console.log(err.toString());

                        if (err.toString().indexOf('cannot be null') >= 0) {
                            response = errorCodes.not_null_parameters;
                            callback(null, response);
                        }
                        response = errorCodes.internal_server_error;
                        callback(null, response);

                    }
                    else {
                        response = {
                            "statusCode": 200,
                            "headers": {
                                "Content-Type": "application/json"
                            },
                            "body": JSON.stringify({ status: 1 }),
                            "isBase64Encoded": false
                        };
                        
                    }
                });
            }
        })
        callback(null, response);
    }
};

这也给出了与上述相同的结果。

为什么我的async电话打不通?

4

1 回答 1

-1

默认情况下mysql,模块函数是基于回调的,因此使用async/await不会起作用。请参阅此处的文档,了解如何使用基于 Promise 的函数。

Mysql 承诺示例

const mysql = require('mysql2/promise');
const con = mysql.createConnection({...});

(async () => {
  try {
    const [rows, fields] = await connection.execute(...);
    // do something with result
  } catch (err) {
    // handle error
  }
})();

完成后,像这样更新您的处理程序函数签名,即忽略第三个参数。

exports.handler =  async function(event, context)

一个简化的版本,跳过了这个想法演示不需要的代码。

const mysql = require('mysql2/promise');

exports.deleteSellerPortfolioItemImages = async (event, context) => {
    if (event.body) {
        return errorCodes.missing_parameters;
    }
   
    const body = JSON.parse(event.body);
    let images;
    
    try {
      images = validateData(body);
    } catch (err) {
      return errorCodes.invalid_parameter;
    }
    
    const sql = "DELETE FROM seller_portfolio_item_images WHERE idseller_portfolio_item_images = ? ";
    
    const promises = images.map(async (item) => {
      return con.execute(sql, [item]);
    });

    try {
      await Promise.all(promises);
    } catch (err){
      if (err.toString().indexOf('cannot be null') >= 0) {
        return errorCodes.not_null_parameters;
      }
      return errorCodes.internal_server_error;
    }
    
    return {
      'statusCode': 200,
      'headers': {
          'Content-Type': 'application/json'
      },
      'body': {
        status: 1
      },
      'isBase64Encoded': false
    };
};

/**
 *
 */
function validateData (body) {
  // TODO: throw error on invalid data
  // otherwise return an array of idseller_portfolio_item_images
}

注1

forEach函数为数组中的每个元素执行给定的函数(在您的情况下为异步函数),但它不等待异步函数结果。有多种方法可以解决此示例代码

选项 1

const promises = body.map(async () => {....});

// using 'all' just for demo use appropriate function in your case
await Promise.all(promises);

选项 2

const promises = [];

body.forEach(()=>{
  // add the promise promises array
  promises.push(...)
});

// using 'all' just for demo use appropriate function in your case
await Promise.all(promises);

笔记2

从 aws lambda 函数直接连接到 Mysql DB 是个坏主意。对于 lambda 函数的每次执行,它将创建一个到 db 的新连接。这会给数据库服务器带来不必要的负载,我建议您查看连接池。鉴于它的 lambda 函数在函数内进行连接池是非常没用的。结帐AWS RDS 代理

于 2021-10-26T07:32:23.577 回答