Избегайте повторного вызова с обратным вызовом при использовании forEach - PullRequest
0 голосов
/ 21 мая 2018

У меня есть функция, которая обрабатывает массив данных (первый параметр) и, как только обработка завершается, она вызывает только один раз функцию обратного вызова (второй параметр).Я использую forEach для обработки элемента данных за элементом, состоящим из обработки каждого элемента в некоторых проверках и сохранения параметра в базе данных.Функция storeInDB() выполняет сохранение и использует обратный вызов (второй параметр) после сохранения элемента.

Первый подход к коду следующий:

function doWork(data, callback) {
    data.forEach(function (item) {
        // Do some check on item
        ...
        storeInDB(item, function(err) {
           // check error etc.
           ...
           callback();
        });
    });
}

Однако, это неправильно, поскольку функция callback будет вызываться несколько раз (столько же, сколько элементов в массиве data).

Я хотел бы знать, как выполнить рефакторинг моего кода, чтобы достичьжелаемое поведение, то есть только один вызов callback после завершения работы по сохранению.Я думаю, что async мог бы помочь в этой задаче, но я пока не нашел подходящего шаблона для объединения async + forEach.

Любая помощь приветствуется!

Ответы [ 3 ]

0 голосов
/ 21 мая 2018

Если функция storeInDB возвращает обещание, вы можете поместить все асинхронные функции в массив и использовать Promise.all .После успешного выполнения всех задач будет вызвана функция обратного вызова.

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

function doWork(data, callback) {
  let arr = [];
  data.map(function(itm) {
    // Do some check on item
    ...
    arr.push(storeInDB(item));
  });
  Promise.all(arr)
    .then(function(res) {
      callback();
    });
}
0 голосов
/ 21 мая 2018

Вы также можете использовать три параметра, переданные функции для выполнения в каждом методе массива

function doWork(data, callback) {

    data.forEach(function (value,idx,arr) {
        // Do some check on item
        ...
        storeInDB(arr[idx], function(err) {
            // check error etc.
            ...
            if ( (idx + 1) === arr.length ) {
                callback();
            }
        });
    });
 }
0 голосов
/ 21 мая 2018

Для этого вы можете использовать библиотеку, например async, хотя я бы порекомендовал использовать обещания, если это возможно.При возникновении непосредственной проблемы вы можете использовать счетчик, чтобы определить, сколько вызовов хранилища завершено, и вызвать обратный вызов, когда общее количество завершено.

let counter = 0;
data.forEach(function (item) {
    // Do some check on item
    ...
    storeInDB(item, function(err) {
       // check error etc.
       counter++
       if (counter == data.length) {
         callback();
       }
    });
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...