2014-10-11 88 views
2

我有以下代碼從MySQL數據庫獲取信息。 DB包括幾個表格,其中包括具有channelId字段的Activity表格,具有userId字段的Channel表格和具有userName字段的User表格。 功能getAllProjectACtivities(user,project)返回一個Activity對象數組的承諾,每個對象都包含所有Activity表字段。 函數findChannel(channelId)返回單個對象的承諾,包括所有的Channel表字段。 功能findUser(userId)返回單個User對象的承諾,包括所有User表字段。 所有3個函數都向數據庫隱藏了一個JSON Ajax請求,並且已經過測試以獨立運行。JavaScript Promise.all代碼不能按預期工作

我在這裏要做的是獲取活動列表,爲他們每個人獲取頻道,爲每個頻道獲取用戶。然後我建立一個由2個活動字段和一個用戶字段組成的活動表。

爲此,我需要一個3階段的數據庫訪問,產生對象數組。下面是代碼:

$(document).ready(function(){  
    var projNum=1; 
    var userNum=1; 
    var globalActivityList; //this global array will store data from the beginning of the promise chain to be used at the end of the chain 
    $('#tableContainer').append('<table border="0" style="background-color: lightblue;"></table>'); 
    var table = $('#tableContainer').children(); 
//here goes: 
    getUserProjectActivities(userNum,projNum) 
     .then(function (activityList){ 
      table.append("<tr><th>Number</th><th>Description</th><th>Employee</th></tr>"); 
      globalActivityList=activityList; 
      return Promise.all(activityList.map(function(activity){ 
       //alert(activity.activityChannelId);//******** shows the right stuff 
       findChannel(activity.activityChannelId); 
      })); 
     }) 
     .then(function (channelList){ 
      alert (channelList.length);//******* gives the right size 
      alert (channelList);//******** u-oh, this shows ,,,,,,,,,,,, - the array is empty.<<<<<<<<<<<<<<<Problem 
      return Promise.all(channelList.map(function(channel){ 
       findUser(channel.channelEmployeeId); 
      })); 
     }) 
     .then(function(userList){ 
      for (var i=0; i<userList.length; i++){ 
       var tableString="<tr>"; 
       tableString+="<td>"+globalActivityList[i].activitityId+"</td>"; 
       tableString+="<td>"+globalActivityList[i].activitityDescription+"</td>"; 
       tableString+="<td>"+userList[i].userName+"</td>"; 
       tableString+="</tr>"; 
       table.append(tableString); 
      } 
     }) 
}); 

接下來會發生什麼,然後獲取一個沒有信息的數組,然後所有後續代碼都失敗。 有什麼想法?謝謝。

回答

5

這些回調需要return承諾,因爲它們是異步的。您的map調用當前會生成undefined的數組,並將其輸入Promise.all。它需要

return Promise.all(activityList.map(function(activity){ 
    return findChannel(activity.activityChannelId); 
// ^^^^^^ 
})); 

return Promise.all(channelList.map(function(channel){ 
    return findUser(channel.channelEmployeeId); 
// ^^^^^^ 
})); 

請注意,您globalActivityList是相當的反模式。它會更好,如果每個activitiy,您將創建一個對象,其中包括渠道和用戶,使所有這些對象的列表變成一個承諾的結果 - 沒有必要離開鏈條:

getUserProjectActivities(userNum, projNum) 
    .then(function(activityList) { 
     table.append("<tr><th>Number</th><th>Description</th><th>Employee</th></tr>"); 
     return Promise.all(activityList.map(function(activity) 
      return findChannel(activity.activityChannelId); 
      .then(function(channel) { 
       return findUser(channel.channelEmployeeId); 
      }) 
      .then(function(user) { 
       // maybe unnecessary intermediate object 
       return {activity:activity.activityID, description:activity.activityDescription, user:user.userName}; 
      }) 
      .then(function(item) { 
       var tableString="<tr>"; 
       tableString+="<td>"+item.activitity+"</td>"; 
       tableString+="<td>"+item.description+"</td>"; 
       tableString+="<td>"+item.user+"</td>"; 
       tableString+="</tr>"; 
       return tableString; 
      }); 
     })); 
    }) 
    .then(function (list) { 
     for (var i=0; i<list.length; i++){ 
      table.append(list[i]); 
     } 
    }); 
+0

享受你的銀色徽章:) – 2014-10-11 15:57:55

+0

@BenjaminGruenbaum:哦,謝謝 - 我有點晚了[聚會](http: //堆棧溢出。com/help/badges/4124/promise):-) – Bergi 2014-10-11 16:04:26

+1

如果標籤我很在意假期,直到第21天:) – 2014-10-11 16:05:39

2

問題出在你如何使用.map.map中的回調應該返回一些內容。

.all需要一個承諾數組,這不是你給的,因爲你沒有正確使用.map

使用Promise.all(arr.map(...))的模式意味着將數組映射到承諾數組中。由於您沒有從.map中的回調中返回任何內容,因此您沒有給予.all預期的結果。

我相信你的意思是return findUser(...);return findChannel(...);(假設他們回覆承諾)。

+0

你對。我想在同一天學習承諾和array.map是有點太... ...) – 2014-10-11 17:17:46