Использование async / await с циклом forEach

Старая почта, которую я знаю, но хотела бросить там. Я узнал на tidyverse, так что лучше или хуже я избегаю базы R, когда это возможно. Я тоже хотел использовать DC, поэтому сначала я построил пешеходный переход:

library(tidyverse)

 st_crosswalk <- tibble(state = state.name) %>%
   bind_cols(tibble(abb = state.abb)) %>% 
   bind_rows(tibble(state = "District of Columbia", abb = "DC"))

Затем я присоединил его к моим данным:

left_join(data, st_crosswalk, by = "state")
728
задан Jack Bashford 22 June 2019 в 02:20
поделиться

1 ответ

Чтобы видеть, как это может пойти не так, как надо, распечатайте console.log в конце метода.

Вещи, которые могут пойти не так, как надо в целом:

  • Произвольный порядок.
  • printFiles может закончить работать прежде, чем распечатать файлы.
  • Низкая производительность.

Они не всегда неправильно, но часто находятся в стандартных вариантах использования.

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

import fs from 'fs-promise'

async function printFiles () {
  const files = (await getFilePaths()).map(file => fs.readFile(file, 'utf8'))

  for(const file of files)
    console.log(await file)
}

printFiles()

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

Это будет:

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

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

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

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

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

Производительность не всегда предсказуема. В то время как много систем будут быстрее с параллельными чтениями файла, некоторые предпочтут последовательный. Некоторые являются динамичными и могут сместиться при загрузке, оптимизации, которые предлагают задержку, не всегда приводят к хорошей пропускной способности в соответствии с тяжелой конкуренцией.

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

Подробно экспериментирование рекомендуется с console.log на каждом этапе и поддельных решениях для чтения файла (случайная задержка вместо этого). Хотя много решений, кажется, делают то же в простых случаях, у всех есть тонкие различия, которые берут некоторое дополнительное исследование для отжимания.

Использование эта насмешка, чтобы помочь сказать различие между решениями:

(async () => {
  const start = +new Date();
  const mock = () => {
    return {
      fs: {readFile: file => new Promise((resolve, reject) => {
        // Instead of this just make three files and try each timing arrangement.
        // IE, all same, [100, 200, 300], [300, 200, 100], [100, 300, 200], etc.
        const time = Math.round(100 + Math.random() * 4900);
        console.log(`Read of ${file} started at ${new Date() - start} and will take ${time}ms.`)
        setTimeout(() => {
          // Bonus material here if random reject instead.
          console.log(`Read of ${file} finished, resolving promise at ${new Date() - start}.`);
          resolve(file);
        }, time);
      })},
      console: {log: file => console.log(`Console Log of ${file} finished at ${new Date() - start}.`)},
      getFilePaths: () => ['A', 'B', 'C', 'D', 'E']
    };
  };

  const printFiles = (({fs, console, getFilePaths}) => {
    return async function() {
      const files = (await getFilePaths()).map(file => fs.readFile(file, 'utf8'));

      for(const file of files)
        console.log(await file);
    };
  })(mock());

  console.log(`Running at ${new Date() - start}`);
  await printFiles();
  console.log(`Finished running at ${new Date() - start}`);
})();

0
ответ дан 22 November 2019 в 21:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: