有一个NodeJS流程可以通过Web服务访问一个名为Kudos的东西。这些荣誉从一个人发送到另一个人/或一群人。我要做的是创建一条包含以下内容的消息:
从{poster}到{receiver / s}的荣誉
{Kudos Message}
目前我的流程正常工作,可以将海报发送到一个接收器。我正在努力使其能够获得接收器的多个名称。
问题源于这样一个事实:它返回接收赞誉的用户的部分,它只提供用户ID。所以我需要再打一次电话来获取用户的名字。我很容易得到承诺,为一个用户工作,但我似乎可以正确地获得多个用户。
包含多个用户的JSON数据如下所示:
"notes_user": [
{
"id": "1060",
"note_id": "795",
"user_id": "411"
},
{
"id": "1061",
"note_id": "795",
"user_id": "250"
},
{
"id": "1062",
"note_id": "795",
"user_id": "321"
}
],
以下是完成大部分工作的功能:
getMaxId返回当前处理过的最高荣誉的数据库索引,而getKudos只返回" kudos"的json数据集。
function promisifiedKudos() {
var maxid;
var newmaxid;
Promise.all([getMaxId(), getKudos()])
.then(function(results) {
maxid = results[0];
var kudos = results[1];
newmaxid = kudos[0].id;
return kudos.filter(function(kudo) {
if (maxid < kudo.id) {
return kudo;
}
})
})
.each(function(kudo) {
return getTribeUserName(kudo);
})
.then(function(results) {
return results.map(function(kudo) {
var message = "Kudos from " + kudo.poster.full_name + " to " + kudo.kudo_receiver_full_name + "\r\n";
message += "\r\n";
return message += entities.decode(striptags(kudo.note));
})
})
.each(function(message) {
return postStatus(message);
})
.then(function() {
var tribehr = db.get('tribehr');
console.log(new Date().toString() + ":Max ID:" + newmaxid);
tribehr.update({ endpoint: "kudos" }, { $set: { id: newmaxid } });
})
.done(function(errors) {
console.log("Run Complete!");
return "Done";
});
}
辅助函数getTribeUserName()
function getTribeUserName(kudo) {
return new Promise(function(fulfill, reject) {
var id = kudo.notes_user[0].user_id;
var options = {
url: "https://APIURL.com/users/" + id + ".json",
method: "GET",
headers: {
"Authorization": "Basic " + new Buffer("AUTHCODE" + AUTHKEY).toString('base64')
}
}
request.getAsync(options).then(function(response) {
if (response) {
var data = JSON.parse(response.body)
kudo.kudo_receiver_full_name = data.User.full_name;
fulfill(kudo);
} else {
reject("Get Tribe User Name Failed");
}
});
});
}
我尝试添加一个调用getTribeUserName()的辅助函数,如下所示:
function getTribeUsers(kudo) {
return new Promise(function(fulfill, reject) {
kudo.notes_user.map(function(user) {
//Make calls to a getTribeUserName
})
});
}
但结果是,当最终消息放在一起时,用户名是未定义的。
任何有关如何更好地使用promises的指示都会非常有帮助。这是我第一次与他们一起刺,我希望我朝着正确的方向前进。我知道我需要添加错误检查,但目前我只是想让这个过程适用于多个用户。
答案 0 :(得分:0)
如果您需要使用作为resolve
函数参数传递的promise的结果,那么您可以在then
onFulfilled
回调中捕获它。
如果您需要将链中的then
方法中获得的某些数据传递给另一个then
,您只需将其返回并通过以下onFulfilled
回调来捕获它{1}}。
then
答案 1 :(得分:0)
如果要异步获取多个TribeUserNames,那么您需要以某种方式汇总多次调用getTribeUserNames()
返回的承诺。
你可以写Promise.all(array.map(mapper))
但Bluebird提供更方便的Promise.map(array, mapper)
。
Bluebird的.spread()
也很方便,可以引用maxid
和kudos
。
这是一个我能管理的简单形式:
function promisifiedKudos() {
return Promise.all([getMaxId(), getKudos()])
.spread(function(maxid, kudos) {
var newmaxid = kudos[0].id;
// The following line filters (synchronously), adds TribeUserNames (asynchronously), and delivers an array of processed kudos to the next .then().
return Promise.map(kudos.filter((kudo) => kudo.id > maxid), getTribeUserName)
.then(function(filteredKudosWithTribeUserNames) { // in practice, shorten arg name to eg `kudos_`
return Promise.map(filteredKudosWithTribeUserNames, function(kudo) {
return postStatus("Kudos from " + kudo.poster.full_name + " to " + kudo.kudo_receiver_full_name + "\r\n\r\n" + entities.decode(striptags(kudo.note)));
});
})
.then(function() {
var tribehr = db.get('tribehr');
console.log(new Date().toString() + ":Max ID:" + newmaxid);
return tribehr.update({ endpoint: 'kudos' }, { $set: { 'id': newmaxid } });
});
})
.then(function() {
console.log('Run Complete!');
}).catch(function(error) {
console.log(error);
throw error;
});
}
getTribeUserName()
需要返回一个承诺,可以写成如下:
function getTribeUserName(kudo) {
var options = {
'url': 'https://APIURL.com/users/' + kudo.notes_user[0].user_id + '.json',
'method': 'GET',
'headers': {
'Authorization': 'Basic ' + new Buffer('AUTHCODE' + AUTHKEY).toString('base64')
}
}
return request.getAsync(options).then(function(response) {
// ^^^^^^
if(response) {
kudo.kudo_receiver_full_name = JSON.parse(response.body).User.full_name;
} else {
throw new Error(); // to be caught immediately below.
}
return kudo;
}).catch(function(error) { // error resistance
kudo.kudo_receiver_full_name = 'unknown';
return kudo;
});
}
补充说明:
Promise.map(...).then(...).then(...)
回调中嵌套.spread()
,newmaxid
仍可通过关闭获得,从而避免使用丑陋的外部变量。Promise.map()
是异步的,假设第二次使用postStatus()
。如果情况不是这样,那么代码仍然有效,尽管可能会略有不同。