2016-07-27 33 views
1

我寫的函數序列解析查詢,其中包括解析查詢順序:的Javascript則承諾不再在for循環

var query1 = new Parse.Query(Events); 
    query1.equalTo("id_organizer", $localStorage.username); 
    query1.greaterThanOrEqualTo("date_start",currentTime) 
    query1.each(function(results){ 
      var object = results; 
      eventname = object.get("event_name"); 
      datestart = object.get("date_start"); 
      location = object.get("location"); 
      id_event = object.get("id_event") 
      eventimagefile = object.get("event_image"); 
      eventimageurl = eventimagefile.url(); 
      description = object.get("description"); 
      id_organizer = object.get("id_organizer"); 
      min_twitter_followers = object.get("min_twitter_followers"); 
      min_instagram_followers = object.get("min_instagram_followers"); 
      min_facebook_friends = object.get("min_facebook_friends"); 
      max_number_requests = object.get("max_number_requests"); 
      eventDetails.push({'name':eventname,'location':location, 'datestart':datestart, 'eventphoto':eventimageurl,'organizer':id_organizer, 'description':description, 'minTwitterFollowers':min_twitter_followers, 'minFacebookFriends':min_facebook_friends, 'minInstagramFollowers':min_instagram_followers,'maxNumberRequests':max_number_requests, 'id_event':id_event})  
    }).then(function(){ 

     alert("start") 

     var Attendees = Parse.Object.extend("Attendees"); 
     eventDetails.forEach(function(e){ 
      var query2 = new Parse.Query(Attendees); 
      query2.equalTo("event_id", e.id_event);  
      query2.count({ 
       success: function(number) { 
        e["n_requests_received"] = number; 
        alert("received") 
       } 
      }) 

      var query3 = new Parse.Query(Attendees); 
      query3.equalTo("event_id", e.id_event); 
      query3.equalTo("status", "confirmed") 
      query3.count({ 
       success: function(number) { 
        e["n_requests_confirmed"] = number; 
        // alert("confirmed") 
       } 
      }) 
     }) 

}).then(function(){ 
    alert("end") 
    alert(JSON.stringify(eventDetails)) 
    $scope.events = eventDetails; 
    $localStorage.events = eventDetails; 
    }); 
}) 

可惜警報「結束」的印刷權後,「開始」,而無需等待查詢(query1,query2)在foreach循環內執行。你知道如何在下一次執行之前執行2個查詢來完成for循環嗎?

+0

這是正確的,因爲你的函數中的每個'then'不返回一個承諾,所以,通過承諾的標準機制,結果與undefined值的立即解決的承諾 - 參見[這]( https://stackoverflow.com/documentation/javascript/231/promises/845/promise-chaining#t=201607271444164888416) –

+0

你能告訴我一個解決方案我不明白我應該怎麼把'那麼'。 – ai20

回答

2
.then(function(){ 
     alert("start") 
     var Attendees = Parse.Object.extend("Attendees"); 

     return Promise.all(eventDetails.map(detail => { 
      return Promise.all([new Promise((res, rej) => { 
       var query2 = new Parse.Query(Attendees); 
       query2.equalTo("event_id", detail .id_event);  
       query2.count({ 
        success: function(number) { 
         detail["n_requests_received"] = number; 
         alert("received") 
         res('Some value if required'); //These are needed or promise chain will hang 
        } 
       }); 
      }), 
      new Promise((res, rej) => { 
       var query3 = new Parse.Query(Attendees); 
       query3.equalTo("event_id", detail .id_event); 
       query3.equalTo("status", "confirmed") 
       query3.count({ 
        success: function(number) { 
         detail["n_requests_confirmed"] = number; 
         // alert("confirmed") 
         res('Some value if required'); //These are needed or promise chain will hang 
        } 
       }); 
      })]); 
     })); 
}) 

承諾鏈將等待承諾。這就是說,如果連鎖店中的任何地方都收到未解決的承諾,它將等待該承諾解決。

所以你可以做的是使用Promise.all這需要一系列的承諾,並會在他們這樣做時解決。因此,請在您的數組eventDetails上映射以創建每個單元格的承諾。在每個單元格內使用另一個Promise.all爲您的兩個Query對象創建兩個新的承諾。

這樣你的.then將等待你的eventDetails承諾的數組解決。然後,eventDetails中的每個單元都將等待您的數組查詢解決。

注:new Promise()我們正在創造承諾。它傳遞給你兩個回調來解決或拒絕承諾。這就是你將舊的回調風格API包裝在承諾中的方式。然而,如果你不呼籲他們中的任何一個解決或拒絕,那麼整個承諾鏈可能會掛起(取決於其設計),等待這個承諾解決。

希望是有道理的。這是僞代碼,但你應該明白。


聲明我沒有使用Parse.Query我不知道它是什麼。然而,這種方法是我將如何處理上述使用舊的回調風格API,你基本上有嵌套循環的程序流程。


額外免責聲明:我的例子是使用ES6語法。並非所有的瀏覽器(IE)都支持這一點。


編輯:操作系統要求的版本沒有使用ES6箭頭功能,所以你在這裏。有關StackOverflow的大量關於箭頭函數和Google的信息。正如你所看到的,在語法方面沒有太大的區別。權力來自它如何綁定範圍,以及如何以更實用的方式編寫代碼。

.then(function(){ 
     alert("start") 
     var Attendees = Parse.Object.extend("Attendees"); 

     return Promise.all(eventDetails.map(function (detail) { 
      return Promise.all([new Promise(function (res, rej) { 
       var query2 = new Parse.Query(Attendees); 
       query2.equalTo("event_id", detail .id_event);  
       query2.count({ 
        success: function(number) { 
         detail["n_requests_received"] = number; 
         alert("received") 
         res('Some value if required'); //These are needed or promise chain will hang 
        } 
       }); 
      }), 
      new Promise(function (res, rej) { 
       var query3 = new Parse.Query(Attendees); 
       query3.equalTo("event_id", detail .id_event); 
       query3.equalTo("status", "confirmed") 
       query3.count({ 
        success: function(number) { 
         detail["n_requests_confirmed"] = number; 
         // alert("confirmed") 
         res('Some value if required'); //These are needed or promise chain will hang 
        } 
       }); 
      })]); 
     })); 
}) 
+0

謝謝它的作品。爲了完整性,'e'應該是代碼中的細節。 – ai20

+0

剛剛在ios上測試過,因爲這是離子應用程序的一部分。該承諾不適用於離子ios – ai20

+0

我會更新'e',當我回到桌面上,很高興它幫助。就承諾而言,我認爲你已經有了'.then'方法,你已經在使用承諾了。如果不是,你可以pollyfill它。這是使用最新和最好的功能的問題。並非所有人都支持他們 – ste2425