2013-06-18 2 views
0

Я использую node.jsКак многократно вызывать функцию и ждать завершения до следующего вызова?

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

Что-то вроде этого (метод синхронизации): (обратите внимание, что SomeFunc асинхронная функция)

var totCount = 1000; 
for (var x = 0 ; x < totCount ; x++) { 
    someFunc(x, parm2, parm3, parm4); 
} 

Я понимаю, что в узле, SomeFunc может выполняться в любом порядке, но в этом случае, это абсолютно должен выполняться с x = 0, затем 1, затем 2 и т. д.

Кажется, что вызов асинхронной библиотеки «async.whilst» сделает это, но у меня возникла проблема с переводом примера в мой реальный код жизни.

Вот пример для «async.whilst»:

var count = 0; 

async.whilst(
    function() { return count < 5; }, 
    function (callback) { 
     count++; 
     setTimeout(callback, 1000); 
    }, 
    function (err) { 
     // 5 seconds have passed 
    } 
); 

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

Как это перевести в мой код? (Я предполагаю, что «async.whilst» - правильный подход. Если нет, пожалуйста, укажите правильный подход)

+0

Является ли someFunc синхронным или вы можете предоставить обратный вызов в качестве аргумента, который вызывается, когда это делается? –

+0

Если someFunc не является асинхронным, он не будет выполняться ни в каком порядке, а в порядке вызова функций. –

+0

someFunc является асинхронным.Могу ли я просто добавить аргумент обратного вызова после всех параметров? – SeanDav

ответ

1

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

var count = 0; 
var totCount = 1000; 

async.whilst(
    function() { return count < totCount; }, 
    function (callback) { 
    someFunc(count, parm2, parm3, parm4, callback); 
    count++; 
    }, 
    function (err) { 
     // someFunc has been called totCount times, or an error has occured 
    } 
); 

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

//... 
    function (callback) { 
    someFunc(x, parm2, parm3, parm4); 
    count++; 
    callback(); 
    }, 
// ... 

Update

Делать это без асинхронных/обещаний (не проверено):

var count = 0; 
var totCount = 1000; 

function loop() { 
    // Async lets you provide you own check-method 
    if(count >= totCount) { 
    // Async lets you provide your own done-method 
    return done(); 
    } 

    // Async does setImmediate/process.nextTick somewhere around here 
    myFunc(count, param, param, function() { 
    // Async checks for errors here 
    count++; 
    loop(); 
    }); 
} 

function done() { 
    // Async provides any errors here 
    console.log("done"); 
} 

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

+0

Спасибо за это - протестируйте его сейчас. Как это можно было бы решить без доступа к библиотеке типа Async или Promises? – SeanDav

+1

@SeanDav Я обновил ответ, не используя async. На самом деле это довольно просто. Если это серверный код, я не вижу смысла изобретать колесо. –

+0

Я собираюсь попробовать что-то подобное, не используя async, просто чтобы узнать, как это делается. Ваше решение async.whilst отлично работает. – SeanDav

1

Похоже, вы хотите использовать обещания, предполагая, что вы можете установить someFunc, чтобы он дал обещание. Вы можете сделать что-то вроде этого:

var promise=new Promise().fulfill(); 
var totCount = 1000; 
for (var x = 0 ; x < totCount ; x++) { 
    promise=promise.then(function(){return someFunc(x, parm2, parm3, parm4);}); 
} 
promise.then(function(){console.log("done");}); 

Точный синтаксис будет зависеть от библиотеки обещаний, которую вы решите использовать.

+0

Спасибо за это. Я установил Q до прихода сюда, но решил, что, поскольку я уже использовал «async», я бы попытался использовать «async» решение. Попытайтесь попробовать свой пример, так как он выглядит довольно элегантно и просто. – SeanDav

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