嵌套异步等待函数未在 AWS Lambda 函数中执行
Nested async await function not executing in AWS Lambda Function
问题:我使用异步等待函数的经验很少,我试图在 if-else 语句中执行嵌套的异步等待函数,该语句依赖于更高级别的异步函数在事件检测时执行。我希望从嵌套的异步函数返回成功的 http 响应,但我继续为响应获取空值。然而,嵌套的异步函数在 if-else 语句之外按预期工作。我的目标是简单地将代码的“等待新承诺”部分获取到 return 条件 if-else 语句中的 http 响应。对此的任何帮助表示赞赏。
我的尝试:除了搜索具有类似问题的问题外,我没有真正尝试过任何补救措施,因为我对异步等待函数的性质知之甚少。
代码:
exports.handler = async (event) => {
const sensorId = event.sensorId;
ddb.scan(params, function (err, data) {
if (err) {
console.log("Error", err);
} else {
console.log("Success", data);
console.log(typeof(data));
data.Items.forEach(function (item, index, array) {
console.log("printing", item);
console.log('Testing', item.sensorId.S);
if (item.sensorId.S == sensorId) {
console.log('New sensorId was not created. Already Exists.');
return ;
}
else {
// Here is the nested async await function
async () => {
console.log(event.sensorId);
const req = new AWS.HttpRequest(appsyncUrl, region);
const item = {
input: {
id: event.sensorId,
sensorId: event.sensorId
}
};
req.method = "POST";
req.path = "/graphql";
req.headers.host = endpoint;
req.headers["Content-Type"] = "application/json";
req.body = JSON.stringify({
query: print(createSensor),
operationName: "createSensor",
variables: item
});
console.log(typeof(graphqlQuery));
if (apiKey) {
req.headers["x-api-key"] = apiKey;
} else {
const signer = new AWS.Signers.V4(req, "appsync", true);
signer.addAuthorization(AWS.config.credentials, AWS.util.date.getDate());
}
const data = await new Promise((resolve, reject) => {
const httpRequest = https.request({ ...req, host: endpoint }, (result) => {
let data = "";
result.on("data", (chunk) => {
data += chunk;
});
result.on("end", () => {
resolve(JSON.parse(data.toString()));
});
});
httpRequest.write(req.body);
httpRequest.end();
});
try {
return {
statusCode: 200,
body: data
};
}
catch(err) {
console.log('error', err);
}
};
}});
}
});
预期结果:
Response
{
"statusCode": 200,
"body": {
"data": {
"createSensor": {
"id": "fd78597a-12fd-4bd1-9f9d-6ee1a88e197d",
"digit": null,
"date": null,
"timestamp": null
}
}
}
}
实际结果:
Response
null
您的代码存在一些问题:
- 嵌套的异步函数 — 您正在创建它但从未执行它
async () => { // creates an async anonymous arrow function, that's it
}
两种解决方案:
// wrapping the function in an IIFE create and executes it
(async () => {
})();
// give it a name and execute it later
async main() => {
}
main();
- 您可以通过将传递给 forEach 的回调声明为异步来摆脱嵌套的异步函数:
data.Items.forEach(async (item, index, array) => { // <--- this is async
// ...
const req = new AWS.HttpRequest(appsyncUrl, region);
const item = {
input: {
id: event.sensorId,
sensorId: event.sensorId,
},
};
// ...
});
- 末尾的 try/catch 块不会捕获任何错误。相反,将您创建的 Promise 包装在 try/catch 块中,并在发生错误事件时从内部拒绝:
try {
const data = await new Promise((resolve, reject) => {
const httpRequest = https.request(
{ ...req, host: endpoint },
(result) => {
// ...
result.on("error", (error) => {
reject(error);
});
// ...
}
);
// ...
});
return {
statusCode: 200,
body: data,
};
} catch (err) {
console.log("error", err);
}
- 运行 forEach 内部的异步操作不会执行您打算执行的操作。您可能打算在 所有 sensorsId 创建后 做出响应。真正发生的是您在创建第一个 sensorId 后立即做出响应。那是因为 forEach 同时触发
data.Items
的回调。一个解决方案是使用 map 和 return 一个 Promise 数组,然后您可以使用 Promise.all. 等待
这是最终代码以及我将如何解决它。作为额外,我已经承诺 ddb.scan
所以你不会将回调与承诺和 async/await:
混在一起
const scanAsync = util.promisify(ddb.scan);
exports.handler = async (event) => {
const sensorId = event.sensorId;
try {
const data = await scanAsync(params);
const responses = await Promise.all(
data.Items.map((item) => {
if (item.sensorId.S == sensorId) {
console.log("New sensorId was not created. Already Exists.");
return;
}
const req = new AWS.HttpRequest(appsyncUrl, region);
const item = {
input: {
id: event.sensorId,
sensorId: event.sensorId,
},
};
req.method = "POST";
req.path = "/graphql";
req.headers.host = endpoint;
req.headers["Content-Type"] = "application/json";
req.body = JSON.stringify({
query: print(createSensor),
operationName: "createSensor",
variables: item,
});
if (apiKey) {
req.headers["x-api-key"] = apiKey;
} else {
const signer = new AWS.Signers.V4(req, "appsync", true);
signer.addAuthorization(
AWS.config.credentials,
AWS.util.date.getDate()
);
}
return new Promise((resolve, reject) => {
const httpRequest = https.request(
{ ...req, host: endpoint },
(result) => {
let data = "";
result.on("data", (chunk) => {
data += chunk;
});
result.on("error", (error) => {
reject(error);
});
result.on("end", () => {
resolve(JSON.parse(data.toString()));
});
}
);
httpRequest.write(req.body);
httpRequest.end();
});
})
);
return {
statusCode: 200,
body: responses,
};
} catch (error) {
console.log("error", error);
}
};
希望您能从我的回复中学到一两件事:)。如果您有任何问题,请告诉我。
问题:我使用异步等待函数的经验很少,我试图在 if-else 语句中执行嵌套的异步等待函数,该语句依赖于更高级别的异步函数在事件检测时执行。我希望从嵌套的异步函数返回成功的 http 响应,但我继续为响应获取空值。然而,嵌套的异步函数在 if-else 语句之外按预期工作。我的目标是简单地将代码的“等待新承诺”部分获取到 return 条件 if-else 语句中的 http 响应。对此的任何帮助表示赞赏。
我的尝试:除了搜索具有类似问题的问题外,我没有真正尝试过任何补救措施,因为我对异步等待函数的性质知之甚少。
代码:
exports.handler = async (event) => {
const sensorId = event.sensorId;
ddb.scan(params, function (err, data) {
if (err) {
console.log("Error", err);
} else {
console.log("Success", data);
console.log(typeof(data));
data.Items.forEach(function (item, index, array) {
console.log("printing", item);
console.log('Testing', item.sensorId.S);
if (item.sensorId.S == sensorId) {
console.log('New sensorId was not created. Already Exists.');
return ;
}
else {
// Here is the nested async await function
async () => {
console.log(event.sensorId);
const req = new AWS.HttpRequest(appsyncUrl, region);
const item = {
input: {
id: event.sensorId,
sensorId: event.sensorId
}
};
req.method = "POST";
req.path = "/graphql";
req.headers.host = endpoint;
req.headers["Content-Type"] = "application/json";
req.body = JSON.stringify({
query: print(createSensor),
operationName: "createSensor",
variables: item
});
console.log(typeof(graphqlQuery));
if (apiKey) {
req.headers["x-api-key"] = apiKey;
} else {
const signer = new AWS.Signers.V4(req, "appsync", true);
signer.addAuthorization(AWS.config.credentials, AWS.util.date.getDate());
}
const data = await new Promise((resolve, reject) => {
const httpRequest = https.request({ ...req, host: endpoint }, (result) => {
let data = "";
result.on("data", (chunk) => {
data += chunk;
});
result.on("end", () => {
resolve(JSON.parse(data.toString()));
});
});
httpRequest.write(req.body);
httpRequest.end();
});
try {
return {
statusCode: 200,
body: data
};
}
catch(err) {
console.log('error', err);
}
};
}});
}
});
预期结果:
Response
{
"statusCode": 200,
"body": {
"data": {
"createSensor": {
"id": "fd78597a-12fd-4bd1-9f9d-6ee1a88e197d",
"digit": null,
"date": null,
"timestamp": null
}
}
}
}
实际结果:
Response
null
您的代码存在一些问题:
- 嵌套的异步函数 — 您正在创建它但从未执行它
async () => { // creates an async anonymous arrow function, that's it
}
两种解决方案:
// wrapping the function in an IIFE create and executes it
(async () => {
})();
// give it a name and execute it later
async main() => {
}
main();
- 您可以通过将传递给 forEach 的回调声明为异步来摆脱嵌套的异步函数:
data.Items.forEach(async (item, index, array) => { // <--- this is async
// ...
const req = new AWS.HttpRequest(appsyncUrl, region);
const item = {
input: {
id: event.sensorId,
sensorId: event.sensorId,
},
};
// ...
});
- 末尾的 try/catch 块不会捕获任何错误。相反,将您创建的 Promise 包装在 try/catch 块中,并在发生错误事件时从内部拒绝:
try {
const data = await new Promise((resolve, reject) => {
const httpRequest = https.request(
{ ...req, host: endpoint },
(result) => {
// ...
result.on("error", (error) => {
reject(error);
});
// ...
}
);
// ...
});
return {
statusCode: 200,
body: data,
};
} catch (err) {
console.log("error", err);
}
- 运行 forEach 内部的异步操作不会执行您打算执行的操作。您可能打算在 所有 sensorsId 创建后 做出响应。真正发生的是您在创建第一个 sensorId 后立即做出响应。那是因为 forEach 同时触发
data.Items
的回调。一个解决方案是使用 map 和 return 一个 Promise 数组,然后您可以使用 Promise.all. 等待
这是最终代码以及我将如何解决它。作为额外,我已经承诺 ddb.scan
所以你不会将回调与承诺和 async/await:
const scanAsync = util.promisify(ddb.scan);
exports.handler = async (event) => {
const sensorId = event.sensorId;
try {
const data = await scanAsync(params);
const responses = await Promise.all(
data.Items.map((item) => {
if (item.sensorId.S == sensorId) {
console.log("New sensorId was not created. Already Exists.");
return;
}
const req = new AWS.HttpRequest(appsyncUrl, region);
const item = {
input: {
id: event.sensorId,
sensorId: event.sensorId,
},
};
req.method = "POST";
req.path = "/graphql";
req.headers.host = endpoint;
req.headers["Content-Type"] = "application/json";
req.body = JSON.stringify({
query: print(createSensor),
operationName: "createSensor",
variables: item,
});
if (apiKey) {
req.headers["x-api-key"] = apiKey;
} else {
const signer = new AWS.Signers.V4(req, "appsync", true);
signer.addAuthorization(
AWS.config.credentials,
AWS.util.date.getDate()
);
}
return new Promise((resolve, reject) => {
const httpRequest = https.request(
{ ...req, host: endpoint },
(result) => {
let data = "";
result.on("data", (chunk) => {
data += chunk;
});
result.on("error", (error) => {
reject(error);
});
result.on("end", () => {
resolve(JSON.parse(data.toString()));
});
}
);
httpRequest.write(req.body);
httpRequest.end();
});
})
);
return {
statusCode: 200,
body: responses,
};
} catch (error) {
console.log("error", error);
}
};
希望您能从我的回复中学到一两件事:)。如果您有任何问题,请告诉我。