2012-01-24 15 views
5

mam coś takiego:Skąd wiadomo, kiedy kończy się ostatnia asynchronizacja?

for (var i=0;i<result.qry.ROWCOUNT;i++) { 
    myAsync(i); 
} 

Skąd mam wiedzieć, kiedy wszystkie moje funkcje asynchroniczne zakończeniu wykonywania?

Na ryzyko, że ktoś odpowie "Potrzebuję więcej jQuery!", Czy mogę użyć obiektu obietnicy jQuery? Lub odroczone czy coś w tym stylu?

+0

z jQuery można użyć '.done()' lub '.Następnie()' '$ połączeniu z .Przy()': http : //stackoverflow.com/a/5817886/1095206 – BartekR

+0

Dziękuję bardzo. Tego właśnie szukałem! –

Odpowiedz

1

W jQuery dostępna jest funkcja $.ajaxStop, która działa po uruchomieniu ostatniego Ajaxa.

7

Śledź, ile połączeń asynchronicznych są zaległe. Kiedy skończysz, zmniejsz swój licznik. Gdy dojdziesz do 0, jesteś w ostatnim oddzwonieniu.

var asyncsLeft = 0; 
for (var i=0;i<10;++i){ 
    asyncsLeft++; 
    doSomethingAsyncWithCallback(function(){ 
    // This should be called when each asynchronous item is complete 
    if (--asyncsLeft==0){ 
     // This is the last one! 
    } 
    }); 
} 

Ze względu na jednowątkowym charakter JavaScript nie ma możliwości wyścigu, gdzie można dostać swoją zwrotna wywoływana przed wszystkich połączeń asynchronicznych zostały kolejce. Bezpiecznie jest umieścić wywołanie asyncsLeft++ po doSomethingAsynchronous, jeśli chcesz.

+1

Proponuję coś podobnego: użyj dwóch zmiennych, które traktują całkowitą liczbę zasobów, i jeden, który śledzi ile załadowanych/nieudanych (prawdopodobnie w dwóch innych zmiennych). Z jedną zmienną ryzykujesz małą szansę, że żądanie zakończy się, zanim kod utworzy nowy, co przedwcześnie zakłada, że ​​wszystko jest załadowane (tak, to faktycznie mi się przydarzyło). Ponadto użycie dwóch zmiennych może pokazywać postęp załadowanych zasobów. –

+0

@JeffreySweeney Jeśli wyrzucisz je wszystkie w pojedynczej pętli, to nie, nie ryzykujesz. O to chodzi w moim kursywnym tekście. Żadne wywołania zwrotne nie będą wywoływane, dopóki pętla 'for' nie zostanie zakończona. – Phrogz

-2

Użyj funkcji zwrotnej:

for (var i=0;i<result.qry.ROWCOUNT;i++) { 
    myAsync(i, myCallback); 
} 

function myCallback(i){ 
    //set result.qry.ROWCOUNT to a var somewhere above if it's not available in this scope 
    if(i == (result.qry.ROWCOUNT - 1)){ 
    //now you know you're actually done with all requests 
    } 
} 
function myAsync(i,callback){ 
    ///do work 
    callback(i); 
} 
+1

Działa to tylko wtedy, gdy zadania asynchroniczne kończą się w kolejności, w której zostały uruchomione. –

+0

W tym przypadku 'mojaAsynchronizacja' jest synchroniczna, musisz przekazać wywołanie zwrotne do dowolnej asynchronicznej metody/biblioteki, której używasz. –

+0

doskonały punkt –

1

Jeśli używasz jQuery, można również użyć metod ajaxSend i ajaxComplete zachować swój kod licznika oddzielone od kodu wysyłki.

var ajaxPending = 0; 

function ajax_changed(indicator, pending) { 
    if (pending) 
     $(indicator).show(); 
    else 
     $(indicator).hide(); 
} 

$('#loading-indicator').ajaxSend(function() { 
    ajax_changed(this, ++ajaxPending); 
}); 

$('#loading-indicator').ajaxComplete(function() { 
    ajax_changed(this, --ajaxPending); 
}); 
2

ten sposób byłoby to zrobić:

//Do stuff up here to get records 
var rowCount = result.qry.ROWCOUNT, //Save the row count 
    asyncCount = 0, //The count of complete async calls 
    asyncCallback = function() { 
     //To be called whenever an async operation finishes 
     asyncCount++; //Increment the row counter 
     if (asyncCount >= rowCount) { 
      //Do stuff when they're all finished 
     } 
    }; 

for (var i=0;i<rowCount;i++) { 
    myAsync(i, asyncCallback); 
} 

function myAsync(index, completeCallback) { 
    //Do async stuff with index 
    //Call completeCallback when async stuff has finished or pass it 
    // into the async function to be called 
} 
Powiązane problemy