我正在嘗試在 AWS Lambda (node.js) 中創建函式,它呼叫一些 REST API,并將 API 結果插入 MySQL DB。
雖然要求很簡單,但我在部署到 AWS Lambda 時遇到了一些問題(在我的本地機器上沒有發生),我的第一個 API 呼叫只導致插入了 1 個資料,而第二個 API 呼叫轉發,它插入了所有 4資料如預期。我在堆疊溢位時嘗試了各種可用的解決方案,結果都是一樣的。
另一個問題是結果總是 {"message": "Internal server error"},即使資料在第二個 API 呼叫轉發時正確插入
基本上我對 Node.js 沒有太多經驗,所以如果有人能幫助我,我將不勝感激。
'use strict';
const connection = require('serverless-mysql')({
config: {
host: 'xxxxxx.xxxxx.ap-southeast-1.rds.amazonaws.com',
user: 'xxx',
password: 'xxx',
database: 'xxx_db'
}
})
const axios = require('axios');
exports.handler = (event, context) => {
//Get Data From API
axios.get('https://xxx.xyz/wp-json/wp/v2/posts')
.then(res => {
const headerDate = res.headers && res.headers.date ? res.headers.date : 'no response date';
console.log('Status Code:', res.status);
console.log('Date in Response header:', headerDate);
//this should result 4 data
const posts = res.data;
posts.forEach(post => {
var sql = `INSERT INTO tbl_post(news_id, title, excerpt, content, category, image_link, modified_date, show_in_banner_F, show_in_list_F) VALUES ('${post.id}', '${post.title.rendered}', '${post.excerpt.rendered}', '${post.content.rendered}', '', '${post.yoast_head_json.og_image[0].url}', now(), 0, 0)`;
console.log(sql);
let insert_query = connection.query(sql);
});
console.log("finished");
connection.end();
let responseBody = { message: "OK" };
let response = {
statusCode: 200,
headers: {
"Access-Control-Allow-Headers" : "Content-Type",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "OPTIONS,POST,GET"
},
body: JSON.stringify(responseBody)
};
return response;
})
.catch(err => {
console.log('Error: ', err.message);
let responseBody = { message: "Fail" };
let response = {
statusCode: 200,
headers: {
"Access-Control-Allow-Headers" : "Content-Type",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "OPTIONS,POST,GET"
},
body: JSON.stringify(responseBody)
};
return response;
});
}
uj5u.com熱心網友回復:
首先,forEach回圈將connection.query(sql)多次呼叫函式,然后退出回圈而不實際等待每個查詢完成執行,因此每次運行此回圈時您最終都會執行亂數量的查詢,而不是您想要做的是使用 async/ awaitawait connection.query(sql)以等待回圈內的每個查詢在退出回圈之前完成執行。
另外forEach回圈沒有專為異步代碼,所以你必須要改變這種狀況,以及和使用for...of來代替。而且您還必須使用準備好的陳述句using?而不是插入值 with${variable}來防止 sql 注入。
for (const post of posts) {
const sql = "INSERT INTO tbl_post(news_id, title) VALUES (?, ?)";
const values = [post.id, post.title.rendered];
console.log(mysql.format(sql,values)); // This would log query after values substitution
await connection.execute(sql, values);
}
所以最終的代碼看起來像這樣:
exports.handler = async (event, context) => {
try {
//Get Data From API
const res = await axios.get("https://xxx.xyz/wp-json/wp/v2/posts");
const headerDate = res.headers && res.headers.date ? res.headers.date : "no response date";
console.log("Status Code:", res.status);
console.log("Date in Response header:", headerDate);
//this should result 4 data
const posts = res.data;
for (const post of posts) {
const sql = "INSERT INTO tbl_post(news_id, title) VALUES (?, ?)";
const values = [post.id, post.title.rendered];
console.log(mysql.format(sql, values)); // This would log query after values substitution
await connection.execute(sql, values); // Execute prepares statement first then executes it.
}
console.log("finished");
await connection.end();
let responseBody = { message: "OK" };
let response = {
statusCode: 200,
headers: {
"Access-Control-Allow-Headers": "Content-Type",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "OPTIONS,POST,GET",
},
body: JSON.stringify(responseBody),
};
return response;
} catch (err) {
console.log("Error: ", err.message);
let responseBody = { message: "Fail" };
let response = {
statusCode: 200,
headers: {
"Access-Control-Allow-Headers": "Content-Type",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "OPTIONS,POST,GET",
},
body: JSON.stringify(responseBody),
};
return response;
}
};
作為旁注,如果您想保證回圈內的所有查詢成功或失敗,請考慮使用事務。
專業提示:Promise.all()如果你想同時執行多個異步函式而不是一個接一個地執行,請使用。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/315644.html
標籤:mysql 节点.js aws-lambda 无服务器
上一篇:Lambda函式在完成前退出
