Лямбда вызывает DynamoDB DocumentClient несколько раз через цикл Loop - PullRequest
0 голосов
/ 24 ноября 2018

С Днем Благодарения всех!Я пишу лямбда-функцию, которая вызывает DynamoDB, и я столкнулся с проблемой проектирования / реализации.

У меня следующая структура кода:

exports.handler = function(event, context, callback) {
    documentClient.batchGet(getParams, function(err, data) {
        if (err) {
            console.log(err);
        } else {
         ...
              while (1) {
                    documentClient.scan(scanParams, function(err, data)    
                    {
                        if (err) {
                            console.log(err);
                        } else {
                              ...
                              if (some condition) {
                                   break;
                              }
                         }
                 }
          }
   }

Я не могу вызвать breakизнутри обратного вызова documentClient.Также я не могу передать переменные изнутри обратного вызова documentClient вовне, а затем выйти из цикла while.Я попытался создать переменную в области действия обработчика и присвоить ей значение внутри функции обратного вызова documentClient, но как только код выходит из области действия обратного вызова, это значение стирается, и переменная имеет свое первоначальное значение в области действия обработчика.

Причина, по которой существует цикл while, заключается в том, что при большой таблице сканирование займет более одной пробной версии.

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

Я искал и не могу найти никаких документов по этой проблеме.Заранее спасибо за чтение.

1 Ответ

0 голосов
/ 24 ноября 2018

Предполагая, что вы можете использовать только Node.js 6.x (и не разрешается использовать более новые версии), вот ответ:

// Node.js 6.x answer:

exports.handler = function (event, context, callback) {
    documentClient.batchGet(getParams, function (err, data) {
        if (err) {
            console.log(err);
        } else {
            // ...
            runScan(scanParams, function(err, scanOutput) {
                if (err) return callback(err);
                // do something with scanOutput.
            });
        }
    });
};


function runScan(scanParams, callback) {
    documentClient.scan(scanParams, function (err, data) {
        if (err) return callback(err);
        if (some_condition) {
            var scanOutput = ...;
            return callback(null, scanOutput);
        }

        // Halting condition
        if(!data.LastEvaluatedKey) {
            return callback(new Error('End of scan'));
        }

        scanParam.ExclusiveStartKey = data.LastEvaluatedKey;
        runScan(scanParams, callback);
    });
}

Ключевые выводы:

  • Я переместил функцию сканирования в собственную функцию (runScan()).

  • Вместо использования цикла while мы используем рекурсию: runScan() вызывает сама себя - но с другимExclusiveStartKey - для сканирования следующей партии элементов.

  • runScan() это асинхронный метод: он не возвращает значение в традиционном смысле.Вместо этого требуется функция обратного вызова.Если он обнаруживает ошибку, он вызывает callback(err) (эквивалент выброса исключения).Если он хочет «вернуть значение» своему вызывающему, он вызывает callback(null, value);Вызывающая сторона должна передать функцию обратного вызова (которая принимает два параметра) и проверить их соответственно.

  • Сканирование заканчивается, когда LastEvaluatedKey нет.Здесь он сообщается вызывающей стороне, передавая объект Error (исключение) в качестве первого параметра обратного вызова.

  • Наконец, если вам разрешено использовать Node.js 8.x (или выше), вы можете использовать async / await, что значительно упрощает написание асинхронного кода.

...