Проблема обратного вызова AWS S3 / Javascript

Вышеупомянутый скрипт велик. Я использовал следующие команды для загрузки файлов, а также для вывода вывода в файл, который полезен при отладке, и это распространенное заблуждение, что windows ftp не может выполнять пассивный режим, чтобы команда пассивная была " quote pasv "(я добавил это в скрипт

Sub FtpFileto()
    Set FSO = CreateObject("scripting.filesystemobject")
    F = "C:\FTPScript.txt"
    ' Create the ftpscript to be run

    Open F For Output As #1
    Print #1, "open ftp.server.com" 'replace ftp.server with the server address
    Print #1, "ID" 'login id here
    Print #1, "PWD" 'login password here
    Print #1, "quote pasv" ' passive mode ftp if needed
    Print #1, "cd " & " /dir" 'Directory of file location
    Print #1, "cd " & " subdir" 'Sub-Directory of file location
    Print #1, "ascii"
    Print #1, "prompt"
    'Put the file from the host and save it to the specified directory and filename
    Print #1, "put " & VREDET; """C:\file1.csv"""; ""
    Print #1, "put " & VREDET; """C:\file2.csv"""; ""
    Print #1, "put " & VREDET; """C:\file3.csv"""; ""
    Print #1, "disconnect" 'disconnect the session
    Print #1, "bye"
    Print #1, "exit"
    Close #1
    'Now for the command to upload to the ftpsite and log it to a text file
    ' the trick is to use the standard command shell which allows logging

    Shell "cmd /c C:\WINDOWS\system32\ftp.exe -i -s:C:\FTPScript.txt > c:\ftpuploadlog.txt", vbHide

    End Sub
0
задан motivus 16 January 2019 в 18:24
поделиться

2 ответа

Как уже говорилось, вы должны избегать использования метода обратного вызова при работе с асинхронными операциями на итерациях из-за их сложности.


(Вы можете пропустить этот раздел, если не хотите знать мотивацию подхода к обещаниям).

Просто отметим, что при подходе с обратным вызовом вы должны ждать завершения всех обратных вызовов в вашем getThumbUrls(), используя if, который проверит, были ли вызваны все обратные вызовы, а затем просто вызвать callback(thumbUrls); с все ответы помещаются в ваш массив thumbUrls:

function getThumbUrls(contentIndex, callback) {
  const thumbUrls = [];

  // counter which will increment by one for every callback
  let counter = 0;
  JSON.parse(contentIndex).forEach(videoKey => {
    getThumbFileName(videoKey, function (thumbFileName) {
      thumbUrls.push(CLOUDFRONT_URL + videoKey + '/thumbnails/' + thumbFileName);

      // for each callback response you must add 1 to a counter and then
      counter++;
      // check if all callbacks already has been called
      if (counter === JSON.parse(contentIndex).length) {
        // right here, thumbsUrls are filled with all responses
        callback(thumbUrls);
      }
    });
  });
}

Итак, вы можете использовать обещания, и вам будет достаточно Promise.all для обработки всех ответов от API. Вы можете учиться через Интернет и проверить код ниже, который использует подход обещания. Я добавил несколько комментариев, чтобы помочь вам понять, что происходит.

// when using promises, no callbacks is needed
getThumbUrls(contentIndex)
  .then(function (data) {
    console.log('Returning from getThumbUrls');
    // let's just display thumbUrls[0] for now...
    console.log('The thumbUrls are ' + data[0]);

  })

// when using promises, no callbacks is needed
function getThumbUrls(contentIndex) {
  console.log('Entering getThumbUrls');

  // not needed anymore, Promise.all will return all values
  // var thumbUrls = [];

  // Promise.all receives an array of promises and returns to next .then() all results
  // changing forEach to map to return promises to my Promise.all
  return Promise.all(JSON.parse(contentIndex).map(videoKey => {
    console.log('videoKey = ' + videoKey);

    // returning a promise
    return getThumbFileName(videoKey)
      .then(function (thumbFileName) {
        console.log('Returning from getThumbFileName');
        console.log('Returned thumb filename is ' + thumbFileName);

        return CLOUDFRONT_URL + videoKey + '/thumbnails/' + thumbFileName;
      });
  }))
}

// when using promises, no callbacks is needed
function getThumbFileName(videoKey) {
  console.log('Entering getThumbFileName...');

  const s3 = new AWS.S3({
    apiVersion: '2006-03-01',
    params: {
      Bucket: 'my-bucket-name'
    }
  });

  // Get the name of the file.
  params = {
    Bucket: 'my-bucket-name',
    Delimiter: '/',
    Prefix: videoKey + '/' + THUMBS_FOLDER,
    MaxKeys: 1
  };

  // urlKey not need anymore
  // var urlKey;

  // most of AWS functions has a .promise() method which returns a promise instead calling callback funcions
  return s3.listObjectsV2(params).promise()
    .then(function (data) {
      var thumbsKey = data.Contents;
      //if you want to return only first one thumbsKey:
      return thumbsKey[0];
    })
    .catch(function (err) {
      console.log(err, err.stack);
      callback(err);
      return;
    })
}

Надеюсь, это поможет вам в учебе.

0
ответ дан guijob 16 January 2019 в 18:24
поделиться

Может кто-нибудь показать мне, как заставить исполнение ждать

Это неправильный вопрос. Вы не пытаетесь заставить казнить «ждать» или, по крайней мере, не должны этого делать. Вам просто нужно вызвать обратный вызов в нужном месте - внутри обратного вызова из s3.listObjectsV2(), а не снаружи.

function getThumbFileName(videoKey, callback) {
  ...
  s3.listObjectsV2(params, (err, data) => {
    if (err) {
      ...
    }

    var thumbsKey = data.Contents;
    // MaxKeys was 1 bc first thumbnail key is good enough for now. Therefore, only one iteration.
    thumbsKey.forEach(function (keys) {
      console.log('thumbKey = ' + keys.Key);
      urlKey = keys.Key;
    });

    callback(urlKey); // right
  });

  // wrong // callback(urlKey);

}

Как вы написали, обратный вызов срабатывает после того, как s3.getObjectsV2() начинает работать , а не после того, как завершает (вызывает собственный обратный вызов).

0
ответ дан Michael - sqlbot 16 January 2019 в 18:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: