Я застрял в этом на пару часов, не могу понять, почему эта простая асинхронная функция возвращает пустой массив? Я пытаюсь запросить ряд элементов из своей таблицы DynamoDB с помощью лямбда-функции, но я не могу заставить функцию приостановить работу с помощью async / await, и я не могу понять, почему. Я зарегистрировался после нажатия, и массив заполняется прекрасными объектами, но он просто не дожидается его завершения перед вызовом done. Пожалуйста. Помощь. Схожу с ума.
'use strict';
const AWS = require('aws-sdk');
const docClient = new AWS.DynamoDB.DocumentClient();
exports.handler = async(event, context, callback) => {
const done = (err, res) => {
const response = {
statusCode: err ? '400' : '200',
body: err ? JSON.stringify(err) : JSON.stringify(res),
headers: {
'Access-Control-Allow-Origin': '*'
}
};
callback(null, response);
};
const { body } = event;
// If in prod env, parse
if (typeof body === 'string') {
body = JSON.parse(body);
}
const groupIds = body.groupIds;
let events = [];
await groupIds.forEach(groupId => docClient.query({
TableName: 'events',
IndexName: 'groupId-creationDate-index',
KeyConditionExpression: 'groupId = :g',
ExpressionAttributeValues: { ':g': groupId }
}, (err, data) => {
if (err) {
done(err);
}
else {
events.push(...data.Items);
}
}));
done(null, events);
};





Возвращает пустую функцию, потому что она просто асинхронна, при разрешении await groupIds.forEach она передается в стек api js, а сделано (ноль, события); разрешается до того, как обещание завершено, чтобы избежать этой проблемы, вы можете сделать следующее, чтобы ваша организация событий разрешила массив обещаний, и когда он будет разрешен, просто отправьте его в обратный вызов.
Вы могли бы сделать что-то вроде этого.
let arr=groupIds.map(groupId => docClient.query({
TableName: 'events',
IndexName: 'groupId-creationDate-index',
KeyConditionExpression: 'groupId = :g',
ExpressionAttributeValues: { ':g': groupId }
}))
Promise.all(arr).then(events=>done(null,events))
Я не знаю API docClient, но достаточно, чтобы он возвращал обещание (обратные вызовы устарели), чтобы переменная arr имела массив обещаний, и они были разрешены позже.
Это не столько проблема AWS Lambda, сколько общий вопрос по Javascript, который вам нужно асинхронизировать и ждать немного глубже в ваших вызовах AWS.
Фактически, хотя у вас есть две проблемы,
async / await в этом Сообщение блога.Array.prototype.forEach не является методом async (вставить заметку о шине событий узла yadda yadda). Достойным дополнением к этому может быть найдено здесь.Вы можете попробовать что-то вроде этого:
//Copied from https://codeburst.io/javascript-async-await-with-foreach-b6ba62bbf404
async function asyncForEach(array, callback) {
for (let index = 0; index < array.length; index++) {
await callback(array[index], index, array)
}
}
asyncForEach(
groupIds,
groupId =>
await docClient.query({ ExpressionAttributeValues: { ':g': groupId }, ...params })
.promise()
)
С учетом всего сказанного я рекомендую вам использовать что-то вроде модуля узла async, который позволит вам получать данные параллельно и т.д ... и по-прежнему использовать async и await.
С некоторыми настройками последнее решение сработало. Большое спасибо!