в javascript, каковы лучшие практики для выполнения нескольких асинхронных функций с обратным вызовом? - PullRequest
3 голосов
/ 29 июля 2011

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

Хотя это совершенно точно, это правильно, но не очень эстетично.

// fn responsible for figuring out and calling aysnc funcs
function fn( arg, outNext ) {

        // calculate how many funcs we will be calling
        var waitCt = 0;
        var a, b, c;
        if( a = arg['a'] ) waitCt++;
        if( b = arg['b'] ) waitCt++;
        if( c = arg['c'] ) waitCt++;

        // call funcs
        if( a ) fnArbitrary( arg.a, inNext );
        if( b ) fnRandom( arg, inNext );
        if( c ) fnClueless( 15, inNext );

        // calback func
        function inNext( err ) {

                // wait for one less func
                waitCt--;

                // return err if found
                if( err ) outNext( err );

                // return nada if all funcs performed
                if( waitCt == 0 ) outNext();

                // otherwise we're waiting for other funcs to finish
                return;
        }
}

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

Ответы [ 2 ]

3 голосов
/ 29 июля 2011

Лучшая идея управления, которую я видел для нескольких функций aysnc, - это Deferreds и Futures, как описано в этой статье Script Junkie , этой статье о реализации FutureJS , this MSDN статья и этот вопрос переполнения стека .

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

Управление несколькими асинхронными вызовами с зависимостями между ними действительно очень сложное занятие. Код не только выглядит грязно, но его невозможно прочитать, а еще более невозможно использовать отладчик. Отладка обычно требует выгрузки большого количества информации в файл журнала и последующей попытки разобраться в том, что произошло. Если время связано, то вы действительно в беспорядке. В моем последнем проекте единственная область, в которой у меня все еще есть нерешенная ошибка - это какая-то пропущенная зависимость между четырьмя различными асинхронными вызовами при запуске. Я укрепил код, чтобы сделать так, чтобы ошибка почти никогда не возникала, но она еще не исчезла. Следующий шаг - переключиться на использование deferreds и добавить к нему некоторую формальную структуру.

Что касается некоторых больших библиотек, у нас есть jQuery Defereds , YUI3 имеет Async Queue (что менее мощно, чем обычные отсроченные, но полезные), Dojo имеет Отложенный объект и есть несколько отложенных библиотек, которые не привязаны к основной библиотеке.

1 голос
/ 29 июля 2011

У меня есть функция после утилиты.

var after = function _after(count, f) {
  var c = 0, results = [];
  return function _callback() {
    switch (arguments.length) {
      case 0: results.push(null); break;
      case 1: results.push(arguments[0]); break;
      default: results.push(Array.prototype.slice.call(arguments)); break;
    }
    if (++c === count) {
      f.apply(this, results);
    }
  };
};

// fn responsible for figuring out and calling aysnc funcs
function fn( arg, outNext ) {

    var cb = after(Object.keys(arg).length, function(data) {
      // all finished. Do something
    });

    // replace fa, fb, fc with f['a'], f['b'], f['c']
    Object.keys(arg).forEach(function(k) { f[k](arg[k], cb); });
}

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

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