JavaScript Promise.all代码无法按预期工作

时间:2014-10-11 15:36:46

标签: javascript arrays map promise

我有以下代码从mySQL DB获取信息。 DB包括几个表,其中包括Activity表,具有channelId字段,具有userId字段的Channel表和具有userName字段的User表。 函数getAllProjectACtivities(user,project)返回Activity个对象数组的保证,每个对象包含所有Activity个表字段。 函数findChannel(channelId)返回单个Channel对象的承诺,包括所有Channel表字段。 函数findUser(userId)返回单个User对象的承诺,包括所有User表字段。 所有3个函数都会向数据库隐藏JSON Ajax请求,并且已经过测试,可以独立运行。

我在这里要做的是获取活动列表,为每个活动获取频道,为每个频道获取用户。 然后我构建一个包含2个活动字段和一个用户字段的活动表。

为此,我需要一个三阶段DB访问,产生对象数组。以下是代码:

$(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);
            }
        })
});

第二种情况会发生什么。然后获得没有信息的数组,当然所有后续代码都会失败。 任何的想法?谢谢。

2 个答案:

答案 0 :(得分: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更像是反模式。如果每个活动都会创建一个包含通道和用户的对象,那么所有这些对象的列表将成为单个承诺的结果 - 不需要离开链条会更好:

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]);
      }
  });

答案 1 :(得分:2)

问题在于您如何使用.map.map中的回调应该返回一些内容。

.all需要一系列承诺,并且这不是您提供的承诺,因为您没有正确使用.map

使用Promise.all(arr.map(...))的模式是将数组映射到promises数组中。由于您未在.map的回调中返回任何内容,因此您未给予.all预期的内容。

我相信你的意思是return findUser(...);return findChannel(...);(假设他们返回了承诺)。