我有以下代码从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);
}
})
});
第二种情况会发生什么。然后获得没有信息的数组,当然所有后续代码都会失败。 任何的想法?谢谢。
答案 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(...);
(假设他们返回了承诺)。