2013-07-25 4 views
4

Я получил асинхронную функцию:массив и асинхронная функция обратного вызова

var func = function (arg, next) { 
    var milliseconds = 1000; 
    setTimeout(function(){ 
     console.log (arg); 
     next() 
    } , milliseconds); 
} 

И массив:

var arr = new Array(); 
arr.push (0); 
arr.push (1); 

console.log(arr); 

Я хочу использовать func для каждого элемента моего массива arr:

func(arr[0], function(){ 
    func(arr[1], function(){ 
     console.log("finish"); 
    }) 
}) 

Ok для массива состоял из 2 элементов, но если я получил массив из 1000 элементов, как использовать func за каждый товар в arr?

Как это сделать в цикле?

+1

http://www.sitepoint.com/javascript-large-data-processing/ –

+0

вы говорите о цикле Еогеасп? –

+0

Можете ли вы использовать JQuery? –

ответ

3
var arrayFunc = function(array) { 
    if (array.length > 0) { 
    func(array[0], function() { arrayFunc(array.slice(1)); }); 
    } 
} 

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

EDIT: вот модифицированная версия, которая не копирует массив вокруг:

var arrayFunc = function(array, index) { 
    if (index < array.length) { 
    func(array[index], function() { 
     var newI = index + 1; 
     arrayFunc(array, newI); 
    }); 
    } 
} 

И просто назвать это в первый раз с индексом 0.

+0

Мне нужно начать думать быстрее, это то же самое решение, которое я получил! :) –

+1

Не будет 'array.slice' создать новый массив? Это приведет к потреблению памяти O (n^2). – Zeta

+0

Хороший улов. Для небольших массивов это должно быть хорошо. Если иметь дело с большими объемами данных, то да, это может быть сделано лучше. Отредактировано, чтобы предоставить этот вариант. – Herms

-1

Вы можете цикл через массив

for(var i = 0; i < arr.length; i++){ 
    func(arr[i], function(){...}); 
} 
+0

Это не будет делать их последовательно, как он хочет. Он начнет их сразу, вместо того, чтобы начать следующий после того, как предыдущее было сделано. – Herms

+0

@ Herms Пропущено это, спасибо за разъяснение – verbanicm

0

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

Если вы хотите применить такую ​​же функциональность на массив, то лучше, чтобы обеспечить функцию, которая создает внутреннюю функцию и применяет тайм-аут на это внутренняя функция:

var asyncArraySequence = function (array, callback, done){ 
    var timeout = 1000, sequencer, index = 0; 

    // done is optional, but can be used if you want to have something 
    // that should be called after everything has been done 
    if(done === null || typeof done === "undefined") 
    done = function(){} 

    // set up the sequencer - it's similar to your `func` 
    sequencer = function(){ 
    if(index === array.length) { 
     return done();  
    } else { 
     callback(array[index]); 
     index = index + 1; 
     setTimeout(sequencer, timeout); 
    } 
    }; 
    setTimeout(sequencer, timeout); 
} 

var arr = [1,2,3]; 
asyncArraySequence(arr, function(val){console.log(val);}); 
0

Простой асинхронный цикл:

function each(arr, iter, callback) { 
    var i = 0; 
    function step() { 
     if (i < arr.length) 
      iter(arr[i++], step); 
     else if (typeof callback == "function") 
      callback(); 
    } 
    step(); 
} 

Теперь используйте

each(arr, func); 
0

Вы можете попробовать arr.map

var func = function (arg, i) { 
    var milliseconds = 1000; 
    setTimeout(function(){ 
     console.log (arg); 
    }, milliseconds*i); 
} 

var arr = new Array(); 
arr.push (0); 
arr.push (1); 

arr.map(func); 

Demo и Polyfill for older browsers.

Update: Я думал, что OP хочет перебрать массив и вызвать функцию обратного вызова каждого элемента массива, но я, наверное, неправильно, поэтому вместо того, чтобы удалить ответ я просто держать его здесь, может быть, это было бы быть полезным для кого-то еще в будущем. Это не отвечает на текущий вопрос.

+0

Что бы ты выбрал? Здесь нет никакого смысла. – Bergi

+0

Простите, я не понял, не зацикливание массива и вызов функции? –

+0

карта здесь не помогает. Он не хочет сразу вызвать func() для каждого элемента массива. Он хочет называть его первым элементом и передать ему функцию, которая называет ее второй, и т. Д. – Herms

0

Простое решение будет:

var fn = arr.reduceRight(function (a, b) { 
    return func.bind(null, b, a); 
}, function() { 
    console.log('finish'); 
}); 

fn(); 

демо: http://jsbin.com/isuwac/2/


или если порядок параметров func «s может быть изменен, чтобы получить next обратного вызова в качестве первого параметра, то может быть таким же простым, как:

['a', 'b', 'c'].reduceRight(func.bind.bind(func, null), function(){ 
    console.log('finish'); 
})(); 

demo: http://jsbin.com/ucUZUBe/1/edit?js,console

0

Thanx, @Herms. Рабочий раствор:

var arrayFunc = function(array) { 
    if (array.length > 0) { 
    func(array[0], function() {arrayFunc(array.slice(1)); }); 
    } 
    else 
    { 
    console.log("finish"); 
    } 
} 
arrayFunc(arr); 
Смежные вопросы