2013-12-19 3 views
0

Я ищу совет по расширению a previous accepted answer в отношении прикованных аякс-запросов.Цепочка асинхронного запроса

Следующее решение асинхронно-цепи, был предложен последовательности 3 запроса Ajax:

var step_3 = function() { 
    c.finish(); 
}; 

var step_2 = function(c, b) { 
    ajax(c(b.somedata), step_3); 
}; 

var step_1 = function(b, a) { 
    ajax(b(a.somedata), step_2); 
}; 

ajax(a, step_1); 

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

Я попытался сделать следующее, но, похоже, столкнулись с проблемами определения объема из-за моей признал отсутствие опыта JavaScript:

var asynch  = function (options, fNext) {// do something asynchronously} 
var chain  = {f:[]} // chain of asynchronous functions 
var args  = function(n){ //return arguments to feed n'th asynch function } 
for (n=0;n<N;n++) 
{ 
    var a  = args(n); 
    var ftmp = n==N-1? function(){} : chain.f[n+1] 
    chain.f[n] = function() {asynch(a, ftmp)} 
} 
chain.f[0]() // initiate asynchronous chain 
+0

Что это вы пытаетесь сделать здесь? Вы вообще делаете документ? DOM? Если нет, если вы используете это для вычисления некоторых данных или для обслуживания некоторых данных, то вы можете избежать использования AJAX и попробовать веб-работников. – Mike

+1

Возможно, вам стоит заглянуть в отличную библиотеку асинхронизации: https://github.com/caolan/async и интерфейс обещания jQuery: http://api.jquery.com/category/deferred-object/ – David

+0

Похоже, у вас есть Задача области видимости здесь: 'chain.f [n] = function() {asynch (a, ftmp)}' 'a' и' ftmp' всегда будет равным значению последней итерации через цикл for. классический для проблемы охвата цикла, решается путем предоставления каждой итерации цикла for частного доступа. –

ответ

0

То, что у вас есть, является очень распространенной проблемой для петель. Каждая итерация цикла for использует ту же локальную область, что и родительская функция, что означает, что все, что происходит асинхронно, в конечном итоге будет обращаться к последнему значению цикла, а не к значению в момент его определения. См. Эту скрипту в качестве примера: http://jsfiddle.net/GAG6Q/ Вместо asynch получив вызов 9 раз, он получает один раз вызов со значением 9. Вы можете исправить его, просто предоставив личную область для внутренней части цикла. Вы также захотите обернуть chain.f[n+1] в функции, чтобы вы не пытались назначить undefined в ftmp.

http://jsfiddle.net/GAG6Q/1/

var N = 10; 
var asynch  = function (options, fNext) { 
    console.log(options); 
    setTimeout(fNext,500); 
}// do something asynchronously} 
var chain  = {f:[]} // chain of asynchronous functions 
var args  = function(n){return n;} //return arguments to feed n'th asynch function } 
for (n=0;n<N;n++) 
{ 
    (function(n){ 
     var a  = args(n); 
     var ftmp = n==N-1? function(){} : function(){chain.f[n+1]();}; 
     chain.f[n] = function() {asynch(a, ftmp)} 
    })(n); 
} 
chain.f[0]() // initiate asynchronous chain 
+0

Это прекрасно. Спасибо, Кевин! – jb1

0

Асинхронные петли боль в заднице. Как правило, если вы хотите сделать это вручную, вам нужно переписать цикл for как рекурсивную функцию.

function sequence_synchronous(steps){ 
    for(var i=0; i<steps.length; i++){ 
    steps[i](); 
    } 
    return; 
} 


function sequence_async(steps, callback){ 
    var i = 0; 
    var next_step = function(){ 
    if(i >= steps.length){ 
     callback(); 
    }else{ 
     steps[i](function(){ 
      i++; 
      next_step(); 
     }); 
    } 
    } 
    next_step(); 
} 

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

Я бы очень хотел найти библиотеку, чтобы сделать это для вас.

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