Проблема с обещаниями и обратными вызовами в JS - PullRequest
0 голосов
/ 23 октября 2019

Я пытаюсь получить список объектов из корзины S3, и когда у меня есть список объектов, я хотел бы создать предварительно подписанные URL-адреса для этих объектов. Единственный способ выяснить, как это сделать, - использовать вложенные функции обратного вызова, например:

exports.handler = async (event, context, callback) => {
console.log('processing event: %j', event);

const bucket = process.env['s3_bucket'];
if (!bucket) {
    callback(new Error("s3 bucket not set"));
}

const deviceId = event['deviceId'];

const params = getListObjectsParams(deviceId, bucket);
let count = 0;

await s3.listObjectsV2(params, function (err, data) {
    if (err) callback("Error getting image list: " + err);
    else {
        data.Contents.forEach(function (image) {
            count = count + 1;
            const objectParams = getObjectParams(bucket, image.Key);
            s3.getSignedUrl('getObject', objectParams, function (err, url) {
                if (err) {
                    console.log("Error");
                    console.log(err);
                    //TODO: log error getting pre signed url
                } else {
                    images.push(url);
                }
            });

        });
    }
});

callback(null, images);

};

У меня возникли проблемы с возвратом массива изображений, так как функциязавершается до завершения вызовов listObjectsV2 и каждого из getSignedUrl. Вот мои вопросы.

  1. Как получить выполнение, чтобы дождаться выполнения обещаний, прежде чем завершить выполнение функции?
  2. Если есть лучший способ для размещения этого блока кода, обратные вызовы вложенности выглядят грязно :(

Ответы [ 2 ]

1 голос
/ 23 октября 2019

AWS JavaScript SDK изначально поддерживает обещания. Вместо этого:

s3.listObjectsV2(params, function (err, data) {
    // do something with data here in the callback
});

напишите это:

const data = await s3.listObjectsV2(params).promise();
// do something with data here

Обратите внимание, что await может использоваться только в функции async. Если вы не используете асинхронную функцию, вы можете изготовить ее следующим образом (функция мгновенного вызова асинхронной стрелки):

(async () => {
    const data = await s3.listObjectsV2(params).promise();
    // do something with data here
})();
1 голос
/ 23 октября 2019

Как заставить выполнение дождаться завершения обещаний, прежде чем завершить выполнение функции?

Внутри функции async поместите await перед обещанием.

Вы сделали первые два из них, но s3.listObjectsV2 не возвращает обещание .

Если вы хотите использовать с ним await, тогдаВы должны преобразовать существующий API обратного вызова в обещание

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...