2014-02-07 2 views
1

Я рассматриваю модуль Node.js 'async для решения проблемы. Я осуществил небольшой тест:Является ли вызов Node.js 'async.parallel() синхронным?

var async = require("async"); 

function print(val) { 
    console.log(val); 
} 

async.parallel([ 
    function(cb){ print(1); cb(null); }, 
    function(cb){ print(2); cb(null); }, 
    function(cb){ print(3); cb(null); }, 
    function(cb){ print(4); cb(null); }, 
    function(cb){ print(5); cb(null); } 
], 
    function(err) { 
     if (err) { 
      console.error(err); 
      return; 
     } 
     console.log("Done!"); 
    } 
); 

console.log("Trulu"); 

Могу ли я быть уверен, что журнал вызовов Trulu никогда не будет вызываться перед вызовом async.parallel закончена? Другими словами, все функции и окончательный обратный вызов вызываются до того, как вызывается журнал Trulu?

+1

Это не будет отвечать на Ваш вопрос, и я знаю, что, но я хочу сказать, что вы могли бы обернуть свои вещи в обещание, чтобы убедиться в этом – Sprottenwels

+0

Я предполагаю, что если вы хотите убедиться, что после обратных вызовов вы можете записать свою функцию в журнал обратного вызова. Но я не вижу разницы между этим и Готовым! log – CubanAzcuy

+0

, если вы застряли на async.js, у него есть метод серии, который делает то, что вы хотите. –

ответ

3

Могу ли я быть уверенным, что вызов журнала Trulu никогда не будет вызван до завершения вызова async.parallel?

Звонок сам, да.

Другими словами, все функции

Я так думаю, хотя документы не упоминают. Однако я бы не ожидал никаких изменений, поскольку это, вероятно, нарушит существующий код.

и окончательный обратный вызов, вызванный до того, как журнал Trulu вызывается точно?

Нет. Вы не знаете функций, и когда они асинхронны, окончательный ответ будет выполнен после Trulu. Если все функции синхронны, вы все равно не должны использовать async. Действительно, в то время как async.js действительно использует setImmediateinternally поэтому некоторые функции обратного вызова (к сожалению, трудно определить) будет «asynchronified», но сопровождающий stated:

Да, что делает функции асинхронной остается на усмотрение разработчика

Если вы хотите, чтобы обратные вызовы всегда вызывались асинхронно (после Trulu), даже если функции синхронны, вы можете использовать A+ compliant Promises.

+0

Моя первая мысль: вы ошибаетесь, но вызовы синхронны, поэтому «Trulu' вызывается после« Done! ». +1 – A1rPun

3

Короткий ответ: Нет, они асинхронны.

Длинный ответ:

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

Таким образом, если вы делаете setTimeout без какого-либо времени, и каждая функция возвращается без каких-либо асинхронов, они могут вести себя синхронно, потому что Javascript работает только по одной единице за раз. И так как они, вероятно, начинаются по порядку, это будет выглядеть так, как если бы он выполнялся синхронно.

Возьмите это в качестве примера:

var looping = true; 

setTimeout(function() {looping = false;}, 1000); 

while(looping) { 
    ... 
} 

Этот код никогда не оставит, как SetTimeout никогда не будет запущен. В async.parralel я почти уверен, что каждый обратный вызов будет выполнен после завершения текущего блока. Это означает, что вы всегда будете иметь свой console.log("Trulu"), выполненный перед любым обратным вызовом внутри async.parralel.

Примечание

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

Тем не менее, я считаю, что существует большое недоразумение с термином async. Асинхронный не является синонимом параболизма или одновременным. Асинхрон, просто означает «без порядка во времени». Это может быть одновременным, но это может быть и последовательным. Чтобы запустить асинхронный код в Javascript, вам нужно полагаться на цикл событий.

Цикл событий может обрабатывать только одно событие за раз, setTimeout просто помещает событие в цикл. Как только обработчик событий уходит, он переходит к следующему событию и так далее.

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

+1

Они не кажутся асинхронными с [асинхронной библиотекой, о которой он говорит] (https://github.com/caolan/async) (как ни странно), если только сами функции не делают что-то асинхронное. Ни эксперимент, ни просмотр кода не предполагают, что функции фактически выполняются параллельно *, если только сами функции не делают что-то асинхронное. Например, 'async.parallel' вызывает функции * синхронно *, но я предполагаю, что они будут выполнять асинхронную работу. Честно говоря, странно. –

+0

@ T.J.Crowder Да, я знаю, я объясняю это –

+0

@ T.J.Crowder: JS не может запускать синхронные функции параллельно, так что вы ожидаете :-) – Bergi

1

Поскольку вы используете async уже, async имеет вызов series. Я думаю, что это может быть то, что вы ищете, но предупреждение, это некрасиво (потому что на мой взгляд async.js по своей сути делает беспорядок):

async.series([ 
    parallel, 
    function(callBack){ console.log("Trulu"); callBack(null); } 
]); 

function parallel(callBack){ 

    async.parallel([ 
    function(cb){ print(1); cb(null); }, 
    function(cb){ print(2); cb(null); }, 
    function(cb){ print(3); cb(null); }, 
    function(cb){ print(4); cb(null); }, 
    function(cb){ print(5); cb(null); } 
    ], 
    function(err) { 
     if (err) { 
      console.error(err); 
      return; 
     } 
     console.log("Done!"); 
     callBack(null); 
    } 
); 
} 

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

Другим простым решением было бы построить этот последний вызов, который вы хотите выполнить после того, как встроенный в дозвона async.parallel:

async.parallel([ 
    function(cb){ print(1); cb(null); }, 
    function(cb){ print(2); cb(null); }, 
    function(cb){ print(3); cb(null); }, 
    function(cb){ print(4); cb(null); }, 
    function(cb){ print(5); cb(null); } 
], 
    function(err) {   
     if (err) { 
      console.error(err); 
      return; 
     } 
     console.log("Done!");   
     console.log("Trulu"); // Executes after all your "parallel calls" are done 
    } 
); 
+0

Не могли бы вы объяснить, как это сделать без async? – user3248186

Смежные вопросы