Promise может использоваться для обеспечения порядка асинхронных обратных вызовов.
Взгляните на async#AsyncFunction
в официальном документе
async
пакет
Где бы мы ни принимали асинхронную функцию в стиле узла, мы также напрямую
принять асинхронную функцию ES2017. В этом случае асинхронная функция будет
не будет передан окончательный аргумент обратного вызова, и любая брошенная ошибка будет
используется в качестве аргумента err неявного обратного вызова и возврата
значение будет использоваться в качестве значения результата. (то есть отклонено
возвращаемое Promise становится ошибочным аргументом обратного вызова и разрешенным
значение становится результатом.)
Третий аргумент async#forEachLimit
- это async#AsyncFunction
, так что вы можете просто вернуть ему обещание и позже разрешить обещание, чтобы указать, что его работа завершена.
Ваш код может быть улучшен следующим образом,
async.forEachLimit(inData, 25, function (data, innercallback) {
// we will wait for all async function in here to complete
// then call the innercallback
var asyncPromises = []
myJson.matches.forEach(function (oMatches) {
if (data.$.id == oMatches.SourceId) {
oMatches.ids.forEach(function (odId) {
asyncPromises.push(new Promise(function (resolve, reject) {
client.execute("g.addV('test').property('id', \"" + data.$.id + "\")", {},
function (err) {
setTimeout(function () {
if (err) {
reject(err)
return
}
resolve();
}, 2000);
});
}))
asyncPromises.push(new Promise(function (resolve, reject) {
client.execute("g.V('" + data.$.id + "').addE('matches').to(g.V('xyz'))", {},
function (err) {
setTimeout(function () {
if (err) {
reject(err)
return
}
resolve();
}, 2000);
});
}))
})
} //there is no else case.
})
// Here we can ensure that innercallback is called only for once
Promise.all(asyncPromises)
.then(function () {
innercallback(null)
})
.catch(function (err) {
// handle the error here
innercallback(err)
})
}, outercallback);
Обратите внимание, что вы должны убедиться, что у вас есть поддержка Promise
в вашей среде Node. Встроенный Promise
поддерживается после Node v6. Проверьте здесь .
Обновлено
Я неправильно понял ваши внутренние обратные вызовы, которые они оба должны были завершить до вызова externalcallback. Я исправил это с помощью Promise.all
, который принимает массив Promise
в качестве аргументов и возвращает Promise
, который будет разрешен, если все подпункты Promise
все разрешены или отклонены, если один из подпунктов Promise
s отклонено. См. Promise#all
.
Обновлено (2018.05.14)
Необходимо убедиться, что каждый innercallback
, полученный от AsyncFunction (т. Е. 3-й аргумент async#forEachLimit
) пакета async
, вызывается только один раз во время каждой итерации. Особенно будьте осторожны, когда вы делаете Array#forEach
на каждой итерации, так как это может заставить вас вызывать innercallback
несколько раз за итерацию.
Я обновил блок кода выше, где я забираю все вызовы innercallback
из обратного вызова client.execute
и помещаю все client.execute
в обещание. После этого я собираю все обещания в массив asyncPromises
.
Promise#all
используется, чтобы гарантировать, что все обещания разрешены (то есть все client.execute
s закончены), затем, наконец, вызовите innercallback
. Или, если одно из приведенных выше обещаний отклонено и перехвачено в Promise#catch
, вызовите innercallback
с первым аргументом, который будет причиной ошибки.