Javascript - параллельный вызов функции и возврат комбинированного результата

Это мой первый вопрос, и я пытаюсь изучить javascript / nodejs.

Имею массив x.

var x = [1,2,3,4];

Также у меня есть функция, которая принимает параметр, выполняет некоторую обработку и возвращает json.

function funcName (param){
  //does some external API calls and returns a JSON
  return result;
}

Теперь я ищу, а не повторять массив и снова и снова вызывать функцию, есть ли способ вызвать их параллельно, а затем присоединиться к результату и вернуть его вместе?

Также я ищу способы поймать неудачное выполнение функций. for ex: funcName(3) fails for some reason

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

Get Off My Lawn 27.07.2018 03:57

@GetOffMyLawn совершенно верно, но удаленные вызовы API могут эффективно чередоваться. Что-то вроде Promise.all(items.map(item => fetch(item.url)).then((results) =>....) будет «распараллеливать» в широком смысле этого слова.

Aluan Haddad 27.07.2018 04:05

@AluanHaddad Я ничего не видел о вызовах API (если только я не пропустил), поэтому я предположил, что этого не происходит

Get Off My Lawn 27.07.2018 04:09

@GetOffMyLawn это в комментарии внутри заглушки функции: p

Aluan Haddad 27.07.2018 04:11

@ Aluan-Haddad проблема с Promise.all заключается в том, что он выйдет из строя, если одна итерация из всех не вернется. Мне нужно это уловить и соответствующим образом обработать.

AGkumar 27.07.2018 04:20

@AGkumar, поэтому добавьте .catch(onError) в вызов map

Aluan Haddad 27.07.2018 04:25
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
3
6
1 037
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Комментарии и другой ответ верны. В JavaScript нет возможности параллельной обработки (процессы разветвления не считаются).

Однако вы можете выполнять вызовы API нечетко параллельным образом. Поскольку они асинхронны, сетевой ввод-вывод может чередоваться.

Учтите следующее:

const urls = ['api/items/1', 'api/items/2', etc];

Promise.all(urls.map(fetch))
 .then(results => {
   processResults(results);
});

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

С обработкой ошибок:

const urls = ['api/items/1', 'api/items/2', etc];

Promise.all(urls.map(fetch).map(promise => promise.catch(() => undefined))
 .then(results => results.filter(result => result !== undefined))
 .then(results => {
   processResults(results);
});
Ответ принят как подходящий

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

В этой функции мы делаем следующее:

  • перебрать каждое значение в массиве и создать обещание, которое мы сохраним в массиве
  • Далее создаем вилку
  • Затем мы отправляем данные в вилку с помощью cp.send().
  • Дождитесь ответа и выполните обещание
  • Используя обещание.all, мы можем определить, когда все наши дочерние процессы завершились.
  • Первым параметром будет массив результатов всех дочерних процессов.

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

const { fork } = require('child_process')

let x = [1,2,3,4]

function process(x) {
  let promises = []
  for (let i = 0; i < x.length; i++) {
    promises.push(new Promise(resolve => {
      let cp = fork('my_process.js', [i])
      cp.on('message', data => {
        cp.kill()
        resolve(data)
      })
    }))
  }
  Promise.all(promises).then(data => {
    console.info(data)
  })
}

process(x)

Теперь в нашем дочернем элементе мы можем прослушивать сообщения, выполнять тяжелую работу и возвращать результат (очень простой пример):

// We got some data lets process it 
result = []
switch (process.argv[1]) {
case 1:
  result = [1, 1, 1, 1, 1, 1]
  break
case 2:
  result = [2, 2, 2, 2, 2, 2]
  break
}
 // Send the result back to the main process
process.send(result)

Другие вопросы по теме