2014-04-25 172 views
0

您如何瞭解For循環何時完成迭代並附加回調。
For循環的Javascript結束鏈回調

這是一個函數內許多循環的示例循環,它將記錄插入indexedDB

if (Object.hasOwnProperty("Books")) { 
      for (var i = 0, j = Object["Books"].length; i < j; i++) { 
       server.Book.add({ 
        title: Object["Books"][i].Cat, 
        content: Object["Books"][i] 
       }); 
      } 
     } 

我需要能夠知道每個if語句循環何時完成,然後附加一個回調。所有循環都是異步觸發的,我只需要在所有循環完成時運行一個function_final()而不是在它們被觸發時。

編輯

我迄今爲止嘗試:

InsertDB = { 
    addBook: function(Object) { 
    return $.Deferred(function() { 
     var self = this; 
     setTimeout(function() { 
     if (Object.hasOwnProperty("Book")) {     
      for (var i = 0, j = Object["Book"].length; i < j; i++) { 
       server.Book.add({ 
        title: Object["Book"][i].id, 
        content: Object["Book"][i] 
       }); 
      } 
      self.resolve(); 
     } 
     }, 200); 
    }); 
}, 
    addMagaz: function(Object) { 
    return $.Deferred(function() { 
     var self = this; 
     setTimeout(function() { 

     if (Object.hasOwnProperty("Magaz")) { 
      for (var i = 0, j = Object["Magaz"].length; i < j; i++) {     
       server.Magaz.add({ 
        content: Object["Magaz"][i] 
       }); 
      } 
      self.resolve(); 
     } 
     }, 2000); 
    }); 
}, 
addHgh: function(Object) { 
    return $.Deferred(function() { 
     var self = this; 
     setTimeout(function() { 

     if (Object.hasOwnProperty("MYTVhighlights")) { 
      for (var i = 0, j = Object["MYTVhighlights"].length; i < j; i++) { 
       server.MYTVhighlights.add({ 
        content: Object["MYTVhighlights"][i] 
       }); 
      } 
      self.resolve(); 
     } 
     }, 200); 
    }); 

    }, ect... 

然後在AJAX成功回調:

success: function(data){ 
var Object = $.parseJSON(data); 

    $.when(InsertDB.addBook(Object), 
    InsertDB.addMagaz(Object), 
    InsertDB.addUser(Object), 
    InsertDB.addArticles(Object), 
    InsertDB.addHgh(Object), 
    InsertDB.addSomeC(Object), 
    InsertDB.addOtherC(Object)).done(final_func); 

function final_func() { 
    window.location = 'page.html'; 
    } 

這裏final_func是循環結束前解僱..

感謝

+0

server.Book.add是否返回承諾? – djna

+0

我認爲這正是js承諾的一項任務。爲您的循環創建承諾。解決一次循環完成。在什麼時候換行承諾。然後附加單個回調。 – Olga

+0

是的。它是一個名爲DB.js的IndexedDB插件,您可以附加.done()。請參閱更新後的帖子,添加了我曾嘗試過的 – Awena

回答

0

既然你說server.Book.add()是異步的,你需要知道的方法時異步操作完成,然後你可以使用它來建立一個知道什麼時候完成的系統。所以,關鍵問題(我已經作爲評論早些時候已經提出並且您沒有回答)是如何知道server.Book.add()何時實際完成。如果您使用的是indexedDB,那麼該函數內部的某個地方,有可能是一個具有onsuccessonerror方法,將告訴你什麼時候該特定操作完成,並需要以某種方式得到浮現出來server.Book.add()該信息的請求對象,無論是作爲一個完成回調或返回的承諾(這兩個選項是如何$.ajax()運作爲它的異步行爲。

讓我們假設server.Book.add()返回得到解決或在臺異步.add()操作完成拒絕承諾對象。如果是這樣的話,那麼你可以監控所有的操作都必須在你的循環是這樣完成:

if (obj.hasOwnProperty("Books")) { 
     var promises = [], p; 

     for (var i = 0, j = obj["Books"].length; i < j; i++) { 
      p = server.Book.add({ 
       title: obj["Books"][i].Cat, 
       content: obj["Books"][i] 
      }); 
      promises.push(p); 
     } 
     $.when.apply($, promises).done(function() { 
      // this is executed when all the promises returned by 
      // server.Book.add() have been resolved (e.g. completed) 
     }).error(function() { 
      // this is executed if any of the server.Book.add() calls 
      // had an error 
     }); 
    } 

讓我們假設代替server.Book.add()返回承諾,它有successerror條件的幾個回調。然後,我們可以寫這樣的代碼:

if (obj.hasOwnProperty("Books")) { 
     var promises = [], p; 

     for (var i = 0, j = obj["Books"].length; i < j; i++) { 
      (function() { 
       var d = $.Deferred(); 
       server.Book.add({ 
        title: obj["Books"][i].Cat, 
        content: obj["Books"][i], 
        success: function() { 
         var args = Array.prototype.slice.call(arguments, 0); 
         d.resolve.apply(d, args); 
        }, 
        error: function() { 
         var args = Array.prototype.slice.call(arguments, 0); 
         d.reject.apply(d, args); 
        } 
       }); 
       promises.push(d.promise()); 
      })(); 
     } 
     $.when.apply($, promises).done(function() { 
      // this is executed when all the promises returned by 
      // server.Book.add() have been resolved (e.g. completed) 
     }).error(function() { 
      // this is executed if any of the server.Book.add() calls 
      // had an error 
     }); 
    } 

所以,因爲你已經沒有披露server.Book.add()如何實際上表明瞭自己完成,我不能說,要麼代碼工作的這些塊的原樣。這是爲了演示一旦你知道server.Book.add()完成時如何通信,你如何解決這個問題。

Promises/Deferreds並不是魔術。他們不知道操作何時完成,除非該操作在承諾上調用.resolve().reject()。所以,爲了使用承諾,你的異步操作必須參與使用承諾,或者你必須承諾對普通的完成回調(正如我在第二個代碼塊中所做的那樣)。

僅供參考,我也是你的Object變量更改爲obj,因爲定義了一個名爲Object變量與JavaScript語言內置Object衝突是一種不好的做法。

+0

謝謝你,兄弟。我想出了一些與邏輯非常接近的東西,但沒有寫得很好。我試圖爲每次迭代設置一個計數器,以便與對象的長度進行比較。這是一個很大的幫助。再次感謝 – Awena

+0

server.book使用DB.js,它是indexedDB的包裝http://aaronpowell.github.io/db.js/ – Awena

+0

計數器也可以使用。這就是'$ .when()'裏面的內容,以及我們在承諾之前所做的一切。 – jfriend00

0

使用jQuery時功能

$.when(function1 , function2) 
    .then(myFunc, myFailure); 
+0

這基本上是一個評論,而不是一個答案。 – jfriend00

1

您可以使用JavaScript closures,就像這樣:

if (Object.hasOwnProperty("Books")) { 
    for (var i = 0, j = Object["Books"].length; i < j; i++) { 
     (function(currentBook) 
      server.Book.add({ 
       title: currentBook.Cat, 
       content: currentBook 
      }); 
     )(Object["Books"][i]); 
    } 

    function_final(); 
} 

有關closures你可以參考here更多的信息。

+0

有趣......感謝分享 – Awena

+0

很高興幫助。如果它解決了你的問題,請標記爲答案。 –

+0

這是一篇非常翔實的文章。它沒有解決我的問題。但是謝謝你的時間。 – Awena

0

我會寫在純JS這樣的事情,認爲這是僞代碼:

var totalForLoopsCount = 3; //Predict for loops count here 
var forLoopsFinished = 0; 

function finalFunction() 
{ 
    alert('All done!'); 
} 

function forLoopFinished() 
{ 
    forLoopsFinished++; 
    if(forLoopsFinished == totalForLoopsCount) 
    { 
     finalFunction(); 
    } 
} 

var length = 10; //The length of your array which you're iterating trough 

for(var i=0;i<length;i++) 
{ 
    //Do anything   

    if(i == length-1) 
    { 
     forLoopFinished(); 
    } 
} 

for(var i=0;i<length;i++) 
{ 
    //Do anything   

    if(i == length-1) 
    { 
     forLoopFinished(); 
    } 
} 

for(var i=0;i<length;i++) 
{ 
    //Do anything  

    if(i == length-1) 
    { 
     forLoopFinished(); 
    } 
}