У меня есть функция AWS Lambda. Он просматривает список массива, который представляет собой массив URL-адресов, сохраняет их снимки экрана и помещает их в s3. Как мне вернуть результат этой функции, который представляет собой массив screenshotLinks, содержащий все ссылки на файлы, сохраненные в s3? В конце я использовал функцию обратного вызова, но она просто возвращает null! Я хочу, чтобы функция обратного вызова выводила все ссылки на файлы s3, сохраненные внутри массива screenshotLinks.

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

desktopLinks.forEach(function (url, index) {
      https.request(url, function(res) {
        var data = new Stream();
        res.on('data', function(chunk) {
          // Agregates chunks
          data.push(chunk);

        });

        res.on('end', function() {
          var body = data.read();
          // Once you received all chunks, send to S3
          var currentLink = links[index];
          var linkAddress = encodeURIComponent(currentLink);
          var slashPosition = getPosition(currentLink, '/', 3)+1;
          var linkName = currentLink.substr(slashPosition, currentLink.length)
          var params = {
            Bucket: bucket,
            Key: completeDate + '/screenshots/' + linkName + '.png',
            Body: body
          };
          s3.putObject(params, function(err, data, callback) {
            if (err) {
              console.error(err, err.stack);
            } else {
              bunch = params.Bucket + '/' + params.Key;
              screenshotLinks.push(bunch);
            }
          });
        });
        
      }).end();
     
  })
  callback(null, screenshotLinks)
};
2
Asad Feroz Ali 25 Сен 2018 в 10:08

2 ответа

Лучший ответ

Ваш код управляется событиями / асинхронен, что означает, что вы вызываете обратный вызов до того, как screenshotLinks будет заполнен.

Метод узла http.ClientRequest.end () завершает отправку запроса, но этого не происходит. Это не означает, что ответ был получен и обработан, как это делает асинхронный обработчик событий. Однако обратный вызов выполняется сразу после вызова request.end (), то есть сразу после того, как запрос был отправлен, поэтому screenshotLinks пуст.

Вам необходимо выполнить обратный вызов из обратного вызова, переданного в s3.putObject. Я предлагаю вам передать обратному вызову объект ответа / результата, который указывает, успешно ли был выполнен putObject, и содержит URL-адрес, к которому он относится, а также сообщение об ошибке или ссылку на скриншот, например что-то вроде этого:

      s3.putObject(params, function(err, data, callback) {
        var s3Response;
        s3Response.url = url;
        if (err) {
          s3Response.success = false;
          s3Response.error = err;
          console.error(err, err.stack);
        } else {
          bunch = params.Bucket + '/' + params.Key;
          s3Response.success = true;
          s3Response.screenshotLink = bunch;
        }
        callback(null, s3Response);
      });
1
redbirdo 25 Сен 2018 в 10:04

Я хотел бы предложить вам использовать среду выполнения узла 8.10.

Ref: https : //aws.amazon.com/blogs/compute/node-js-8-10-runtime-now-available-in-aws-lambda/

Тогда ваша точка входа должна быть:

export async function <function_name>(event) {}

Затем:

let s3 = new AWS.S3({ region: process.env.AWS_REGION, apiVersion: '2006-03-01' });
let params= 
{
     Bucket: /* a path to bucket (string) */,
     Key: name /* string */,
     Body: /* supported types (Buffer, Typed Array, Blob, String, ReadableStream) */,
     ACL: 'public-read',
     ContentType: 'image/png'
};

try
{
    let s3Response = await s3.upload(params).promise();
    // if succceed
    console.log(`File uploaded to S3 at ${s3Response.Bucket} bucket. File location: ${s3Response.Location}`);
}
catch (ex) // if error occured
{
    console.error(ex);
}
1
Nikolay Vetrov 25 Сен 2018 в 17:22