Вы будете использовать, и это обещают его версию

внешний интерфейс GitHub Promise ECMAScript 8

Упомянутые здесь методы обхода включают:map,reduce,reduceRight,forEach,filter,some,every
Поскольку в последнее время будет выполняться некоторая агрегация данных,nodeВерсия уже 8.11.1, поэтому и написал прямоasync/awaitсценарий.
Однако при выполнении некоторых операций обхода массива обнаруживается, что некоторые методы обхода не подходят дляPromiseобратная связь не была тем результатом, который мы хотели.

Конечно, некоторые из них не являются строго обходными, напримерsome,everyиз этих.
Но на самом деле они будут вызывать входящий обратный вызов несколько раз в зависимости от элементов нашего массива.

Эти методы относительно распространены, но когда ваша функция обратного вызова являетсяPromiseкогда все изменилось.

предисловие

async/awaitдляPromiseсинтаксический сахар для будет использоваться непосредственно в текстеasync/awaitзаменятьPromise

let result = await func()
// => 等价于
func().then(result => {
  // code here
})

// ======

async function func () {
  return 1  
}
// => 等价与
function func () {
  return new Promise(resolve => resolve(1))
}

map

mapвозможно верноPromiseОдна из самых дружественных функций.
мы все знаем,mapПринимает два параметра:

  1. Обратный вызов выполняется для каждого элемента, возвращаемое значение результата обратного вызова будет использоваться как элемент соответствующего индекса в массиве.
  2. необязательная функция обратного вызоваthisпараметр указывал на
[1, 2, 3].map(item => item ** 2) // 对数组元素进行求平方
// > [1, 4, 9]

Сверху обычныйmapвыполняется, но когда некоторые из наших вычислительных операций становятся асинхронными:

[1, 2, 3].map(async item => item ** 2) // 对数组元素进行求平方
// > [Promise, Promise, Promise]

В настоящее время возвращаемое значение, которое мы получаем, на самом деле являетсяPromiseМассив функций.

Так почему ты говоришьmapфункция самая дружелюбная, потому что мы знаем,PromiseЕсть функция дляPromise.all
будетPromiseСформированный массив последовательно выполняется и возвращаетPromiseОбъект, результатом которого является набор результатов, созданный массивом.

await Promise.all([1, 2, 3].map(async item => item ** 2))
// > [1, 4, 9]

первое использованиеPromise.allоберните массив, затем используйтеawaitПолучите результаты.

reduce/reduceRight

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

  1. Функция обратного вызова выполняется для каждого элемента, возвращаемое значение будет накапливаться при следующем вызове функции, сигнатура функции обратного вызова:
    1. accumulatorнакопленная стоимость
    2. currentValueэлемент в настоящее время обрабатывается
    3. currentIndexНижний индекс элемента, который в данный момент обрабатывается(благодарный@NeurotoxinVXДополнения от друзей)
    4. arrayпередачаreduceмассив
  2. необязательное инициализированное значение, которое будет использоваться какaccumulatorначальное значение
[1, 2, 3].reduce((accumulator, item) => accumulator + item, 0) // 进行加和
// > 6

В этом коде нет ничего плохого, как будто наша операция сложения тоже асинхронная:

[1, 2, 3].reduce(async (accumulator, item) => accumulator + item, 0) // 进行加和
// > Promise {<resolved>: "[object Promise]3"}

Возвращаемый результат будет очень странным, мы оглядываемся на вышеприведенноеreduceсигнатура функции

Функция обратного вызова выполняется для каждого элемента, возвращаемое значение будет накапливаться до следующего вызова функции.

Затем мы снова смотрим на код,async (accumulator, item) => accumulator += item
Об этом было сказано в самом начале, даPormiseСинтаксический сахар , чтобы видеть более ясно, мы можем написать:

(accumulator, item) => new Promise(resolve =>
  resolve(accumulator += item)
)

То есть мыreduceВозвращаемое значение функции обратного вызова на самом деле являетсяPromiseобъект
Тогда у нас естьPromiseвозражать против выполнения+=операция, очень разумно получить такое странное возвращаемое значение.

Конечно,reduceНастройка также очень проста:

await [1, 2, 3].reduce(async (accumulator, item) => await accumulator + item, 0)
// > 6

Мыaccumulatorпередачаawait, а затем с текущимitemсложить, в конце нашreduceВозвращаемое значение также должно бытьPromise, поэтому мы также добавляем самый внешнийawaitшрифт
То есть каждый раз, когда мыreduceвернет новыйPromiseОбъект, внутрь объекта попадет последний разPromiseрезультат.
мы называемreduceПо факту получается вот такPromiseОбъект:

new Promise(resolve => {
  let item = 3
  new Promise(resolve => {
      let item = 2
      new Promise(resolve => {
        let item = 1
        Promise.resolve(0).then(result => resolve(item + result))
      }).then(result => resolve(item + result))
  }).then(result => resolve(item + result))
})

reduceRight

Об этом нечего сказать. . а такжеreduceЭто просто обратный порядок

forEach

forEach, это должен быть наиболее часто используемый метод обхода, соответствующая сигнатура функции:

  1. callback, функция для вызова каждого элемента
    1. currentValue, текущий элемент
    2. index, индекс текущего элемента
    3. array,передачаforEachссылка на массив
  2. thisArg, необязательная функция обратного вызоваthisнаправление

У нас есть следующие операции:

// 获取数组元素求平方后的值
[1, 2, 3].forEach(item => {
  console.log(item ** 2)
})
// > 1
// > 4
// > 9

В обычной версии мы можем напрямую выводить таким образом, но если мы встретимPromise

// 获取数组元素求平方后的值
[1, 2, 3].forEach(async item => {
  console.log(item ** 2)
})
// > nothing

forEachне заботится о возвращаемом значении функции обратного вызова, поэтомуforEachПросто выполните три, вернетесьPromiseФункция
Поэтому, если мы хотим получить желаемый эффект, мы можем только сами улучшить свойства объекта:

Array.prototype.forEachSync = async function (callback, thisArg) {
  for (let [index, item] of Object.entries(this)) {
    await callback(item, index, this)
  }
}

await [1, 2, 3].forEachSync(async item => {
  console.log(item ** 2)
})

// > 1
// > 4
// > 9

awaitбудет игнорировать не-Promiseстоимость,await 0,await undefinedтакой же, как обычный код

filter

filterКак функция для фильтрации массивов, она также имеет функцию обхода:
Сигнатура функции такая же, какforEach,ноcallbackВозвращаемое значениеtrueэлементы будут размещены вfilterвозвращаемое значение функции.

Мы хотим сделать нечетный фильтр, поэтому пишем:

[1, 2, 3].filter(item => item % 2 !== 0)
// > [1, 3]

Затем мы меняем наPromiseВерсия:

[1, 2, 3].filter(async item => item % 2 !== 0)
// > [1, 2, 3]

Это делает наши функции фильтрации неэффективными, потому чтоfilterВозвращаемое значение совпадения не является точным соответствием равенства, если возвращаемое значение может быть преобразовано вtrue, это будет считаться прохождением фильтра.
Promiseобъект должен бытьtrue, поэтому фильтр не работает.
Итак, наш подход такой же, как и вышеforEachТочно так же вам также необходимо выполнить улучшение объекта самостоятельно. Но мы тут прямо выбираем хитрый путь:

Array.prototype.filterSync = async function (callback, thisArg) {
  let filterResult = await Promise.all(this.map(callback))
  // > [true, false, true]

  return this.filter((_, index) => filterResult[index])
}

await [1, 2, 3].filterSync(item => item % 2 !== 0)

Мы можем напрямую позвонить внутрьmapметод, как известноmapВсе возвращаемые значения будут возвращены в виде нового массива.
Это также означает, что мыmapможет получить нас всехitemрезультат фильтрации,trueилиfalse.
Затем верните результат соответствующего индекса каждому элементу исходного массива.

some

someВ качестве функции для определения того, удовлетворяет ли массив некоторым условиям, ее также можно использовать для обхода
Сигнатура функции такая же, какforEach, разница в том, что когда либоcallbackВозвращаемое значение соответствуетtrueвернется прямоtrue, я упалcallbackспичкиfalse, затем вернутьсяfalse

Мы хотим проверить, равен ли какой-либо элемент массива2:

[1, 2, 3].some(item => item === 2)
// > true

Затем мы меняем его наPromise

[1, 2, 3].some(async item => item === 2)
// > true

Эта функция все равно вернетtrue, но не то, что мы хотим, потому что этоasyncвернутьPromiseобъект идентифицируется какtrue.

Итак, мы должны сделать следующее:

Array.prototype.someSync = async function (callback, thisArg) {
  for (let [index, item] of Object.entries(this)) {
    if (await callback(item, index, this)) return true
  }

  return false
}
await [1, 2, 3].someSync(async item => item === 2)
// > true

потому чтоsomeсоответствует первомуtrueПосле этого обход будет прекращен, поэтому мы используем его здесьforEachЭто пустая трата производительности.
также используетсяawaitбудет игнорировать преимущества обычных выражений и использовать их внутриfor-ofчтобы удовлетворить наши потребности

every

и наш последнийevery
Сигнатура функции такая же, какforEachТакой же,
ноcallbackЕсть еще некоторые отличия в обработке:
На самом деле, с другого ракурса,everyэто обратная сторонаsome
someполучит первыйtrueпрекращается, когда
а такжеeveryполучит первыйfalseзавершается, если все элементыtrue, затем вернутьсяtrue

Мы хотим определить, все ли элементы в массиве больше 3

[1, 2, 3].every(item => item > 3)
// > false

Очевидно, что ни одно из них не совпадает, и функция обратного вызова завершилась при первом выполнении и больше не будет выполняться.
мы меняем наPromiseВерсия:

[1, 2, 3].every(async => item > 3)
// > true

Это должно бытьtrue, потому что мы судим, чтоPromiseобъект
Итак, мы берем верхsomeSyncРеализация немного изменена:

Array.prototype.everySync = async function (callback, thisArg) {
  for (let [index, item] of Object.entries(this)) {
    if (!await callback(item, index, this)) return false
  }

  return true
}
await [1, 2, 3].everySync(async item => item === 2)
// > false

при совпадении с любымfalse, вернуться напрямуюfalse, чтобы завершить обход.

постскриптум

Существует несколько методов обхода массивов.
потому чтоmapа такжеreduceфункции, поэтому используетasyncфункционировать с минимальными изменениями.
reduceРезультат очень похож на модель лука
Но для других функций обхода в настоящее время вам нужно реализовать это самостоятельно.

четыре*SyncРеализация функции:GitHub.com/J IA SM/примечание B…

использованная литература

Array - JavaScript | MDN