Nano Hash - криптовалюты, майнинг, программирование

Шаблон проектирования параллельного обратного вызова nodejs

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

Позвольте мне сформулировать задачу, чтобы проиллюстрировать это. Задачи a, b, c, d, e, f, g выполняются как a(function(er, ra){//task a returned, ra is result}), так что от b до g

Есть также некоторые задачи, которые должны быть выполнены после выполнения некоторой задачи, назовем их ab, bc, abc, bd, bcd, af, fg, это означает, что когда a и b вернулись, ab(ra, rb) должны выполняться сразу, а когда b и c возвращаются, bc(rb, rc) должен выполняться одновременно, и если a, b, c все возвращены, abc(ra, rb, rc) должен быть выполнен.

В простейшем случае, если есть только a и b, я могу сделать что-то вроде этого:

(function(cb){
    var count = 2, _ra, _rb;
    function update(){if(--count == 0) cb(null, _ra, _rb)}
    a(function(er, ra){_ra = ra; update()});
    b(function(er, ra){_rb = rb; update()});
})(function(er, ra, rb){
    ab(ra, rb);
});

Как видите, a и b выполняются параллельно, а когда оба они выполнены, ab(ra, rb) выполняются.

Но как я могу сделать больше для множества параллельных задач?


Ответы:


1

На самом деле вам нужен отложенный шаблон, подобный фьючерсам.

function defer(f) {
    // create a promise.
    var promise = Futures.promise();
    f(function(err, data) {
        if (err) {
            // break it
            promise.smash(err);
        } else {
            // fulfill it
            promise.fulfill(data);
        }
    });
    return promise;
}
var da = defer(a), db = defer(b), dc = defer(c), dd = defer(d), de = defer(e), df = defer(f), dg = defer(g);

// when a and b are fulfilled then call ab
// ab takes one parameter [ra, rb]
Futures.join(da, db).when(ab);
Futures.join(db, dc).when(bc);
// abc takes one parameter [ra, rb, rc]
Futures.join(da, db, dc).when(abc);
Futures.join(db, dd).when(bd);
Futures.join(db, dc, dd).when(bcd);
Futures.join(da, df).when(af);
// where's e ?
Futures.join(df,dg).when(fg);
Futures.join(da,db,dc,dd,de,df,dg).fail(function() {
    console.log(":(");
});
13.05.2011
  • Это почти как музыка, это так красиво 13.05.2011
  • Действительно ли это обрабатывает эти задачи параллельно, когда node.js является однопоточным, работающим в одном процессе? Или это перемещение задач в конец очереди событий для обработки позже, когда очереди событий больше нечего делать? 17.05.2011
  • @AntKutschera многопоточности нет. Это просто говорит, что запускайте a-g параллельно (там асинхронно обрабатывается другим процессом в другом потоке), и когда любая пара завершает работу, запускайте эту функцию 17.05.2011
  • кто запускает этот дочерний процесс? Библиотека фьючерсов? Как? 17.05.2011
  • @AntKutschera Я предполагал, что a,b,c,d, etc все либо запускают дочерние процессы, либо выполняют асинхронный ввод-вывод через сокет или поток. Node делает минимальный подъем. Фьючерсы - нет. Futures просто говорит, когда и da, и db возвращаются, запускаются ab. 17.05.2011

  • 2

    Вам следует проверить Step (https://github.com/creationix/step). Это чуть более сотни строк кода, так что при необходимости вы можете прочитать все это целиком.

    Мой предпочтительный шаблон выглядит примерно так:

    
    function doABunchOfCrazyAsyncStuff() {
      Step (
        function stepA() {
          a(arg1, arg2, arg3, this); // this is the callback, defined by Step
        }
        ,function stepB(err, data) {
          if(err) throw err; // causes error to percolate to the next step, all the way to the end.  same as calling "this(err, null); return;"
          b(data, arg2, arg3, this);
        }
        ,function stepC(err, data) {
          if(err) throw err;
          c(data, arg2, arg3, this);
        }
        ,function stepDEF(err, data) {
          if(err) throw err;
          d(data, this.parallel());
          e(data, this.parallel());
          f(data, this.parallel());
        }
        ,function stepGGG(err, dataD, dataE, dataF) {
          if(err) throw err;
          var combined = magick(dataD, dataE, dataF);
          var group = this.group();  // group() is how you get Step to merge multiple results into an array
          _.map(combined, function (element) {
            g(element, group()); 
          });
        }
        ,function stepPostprocess(err, results) {
          if(err) throw err;
          var processed = _.map(results, magick);
          return processed; // return is a convenient alternative to calling "this(null, result)"
        }
        ,cb // finally, the callback gets (err, result) from the previous function, and we are done
      );
    }
    

    Примечания

    • В моем примере также используется библиотека подчеркивания, «галстук для соответствия смокингу JQuery»: http://documentcloud.github.com/underscore/
    • Называть каждую функцию шага stepXXXXX - это хорошая привычка, чтобы трассировки стека были четкими и удобочитаемыми.
    • Step позволяет создавать мощные и элегантные комбинации последовательного и параллельного выполнения. Эти шаблоны просты и понятны. Если вам нужно что-то более сложное, например «когда 3 из 5 из этих методов будут выполнены, переходите к следующему шагу», серьезно ПЕРЕСМОТРИТЕ свой дизайн. Вам действительно нужен такой сложный узор? (возможно вы ждете набора кворума). Такой сложный узор заслуживает отдельной функции.
    23.08.2011
  • групповые задачи параллельны или последовательны 10.03.2012
  • У этого есть несколько недостатков по сравнению с async, а именно, если вы хотите вызвать служебный метод, например, с водопадом, вам понадобится оболочка для обработки ошибки. например: collection.find.bind (...), где вы можете использовать привязки функций к методам в вашей цепочке ... это действительно полезно и не работает с step. 25.07.2013

  • 3

    Попробуйте посмотреть модуль step и эту статью.

    13.05.2011
  • Это должно быть комплиментом. Объяснение того, как использовать step, - вот ответ. 13.05.2011
  • @Raynos, мне потребовалось пару раз прочитать это, чтобы понять, я думаю, вы имели в виду "комментарий", но не меняйте его, потому что это довольно забавно 29.01.2013

  • 4

    да, посмотрите на модуль управления потоком, такой как step, chain или flow ~, и я думаю, что что-то подобное есть и в underscore.js

    13.05.2011

    5

    Очень простой барьер только для этого: https://github.com/berb/node-barrierpoints

    13.05.2011

    6

    nimble - еще один хороший выбор.

    26.08.2013
    Новые материалы

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

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

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

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..