forEach
процессы вещей в серии, так что ради этого ответа, давайте предположим, это требование. Promise.all
, как продемонстрировал @georg, обработает элементы в parallel - это хороший ответ, но это не поможет вам, если серия - это то, что вам действительно нужно.
Методы Array.prototype reduce
, map
и forEach
являются синхронными, но вы можете легко сделать асинхронные варианты. Вы используете forEach
здесь, но вы на самом деле выполняете reduce
вручную. Итак, начнем с внедрения асинхронного reducek
, а затем оттуда
Не беспокойтесь о понимании reducek
. Все, что вам нужно знать, - это основное различие между и reduce
в том, что функция уменьшения получает дополнительный аргумент обратного вызова, который вызывается, когда каждый элемент выполнен, а reducek
имеет свой собственный обратный вызов, когда выполняется весь список ввода. не
function reducek (f, acc, [x, ...xs], k) {
if (x === undefined)
return k (acc)
else
return f (acc, x, y => reducek (f, y, xs, k))
}
function msgAfterTimeout (who, timeout, onDone) {
return setTimeout(onDone, timeout, "Hello " + who + "!")
}
function messageReducer (acc, item, done) {
return msgAfterTimeout(item.name, 200, function (text) {
return done([...acc, text])
})
}
function displayName (list, done) {
// use our async reduce here
return reducek (messageReducer, [], list, done)
}
var list = [{name:"foo",surname:"bar"},{name:"Jean",surname:"dupond"}]
displayName (list, function (texts) {
console.log("Done!", texts.join(' '))
})
// Done! Hello foo! Hello Jean!
Важные вещи, чтобы заметить ...
больше не выполняет уменьшить вручную - вместо того, чтобы использовать переменную test
инициализирована с состоянием ''
(пустая строка), reducek
принимает начальное значение в качестве аргумента.
Здесь мы используем начальное состояние []
(пустой массив) для хранения каждого из текстов. Когда мы закончим, мы объединяем тексты вместе, используя texts.join(' ')
.
Not Another церемонии ...
Все, что есть много церемонии и продолжения не обязательно являются лучшими для контроля асинхронного потока. Фактически, обещания были доведены до JavaScript, потому что нужен был лучший инструмент.
// instead of returning a timeout, return a Promise
function msgAfterTimeout (who, timeout) {
return new Promise(function (resolve) {
setTimeout(resolve, timeout, "Hello " + who + "!")
})
}
// new async/await syntax - work with Promises in a most elegant fashion
// no more callback parameter; async implicitly returns a Promise
async function displayName (list) {
let texts = []
for (let item of list)
texts.push(await msgAfterTimeout(item.name, 200))
return texts
}
var list = [{name:"foo",surname:"bar"},{name:"Jean",surname:"dupond"}]
// instead of a callback, chain a .then on the returned Promise
displayName(list).then(texts => console.log("Done!", texts.join(' ')))
// Done! Hello foo! Hello Jean!
Примечание: Если вам необходимо поддерживать старые браузеры, async
/await
потребности быть transpiled, используя что-то вроде Бабеля.
Что должно содержать результат? Он не определен выше. – Joe