[英]NodeJS Promises: Proper way to combine multiple HTTP requests returns
有一个NodeJS流程可以连接到Web服务获取所谓的Kudos。 这些荣誉从一个人发送到另一个人/或一群人。 我正在尝试做的是创建一条包含以下内容的消息:
从{poster}到{receiver / s}的荣誉
{荣誉消息}
目前,我的程序可以正常工作,以将海报发布给一个接收者。 我正在努力使其与接收者的多个名称一起使用。
问题源于以下事实:返回用户的部分,仅提供用户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
})
});
}
但是结果是,在将完成的消息放在一起时,用户名是不确定的。
关于如何更好地使用Promise的任何指示都将非常有帮助。 这确实是我第一次与他们合作,我希望我朝着正确的方向前进。 我知道我需要添加错误检查功能,但目前我只是想让该流程适用于多个用户。
如果你需要使用作为参数传递一个承诺的结果, resolve
功能,那么你可以在抓住它then
onFulfilled
回调。
如果您需要将在信息链的then
方法中获得的某些数据传递给另一个, then
只需将其返回并通过随后then
的onFulfilled
回调对其进行捕获。
object.somePromise().then(function(param){
var data = someFunction();
return data;
}).then(function(param){
//param holds the value of data returned by the previous then
console.log(param);
});
如果是异步获取多个TribeUserNames的问题,那么您需要以某种方式汇总由多次调用getTribeUserNames()
返回的getTribeUserNames()
。
您可以编写Promise.all(array.map(mapper))
但是Bluebird提供了更方便的Promise.map(array, mapper)
。
蓝鸟的.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()
需要返回一个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;
});
}
进一步说明:
.spread()
回调中嵌套Promise.map(...).then(...).then(...)
, newmaxid
可以通过闭包保持可用,从而避免了使用丑陋的外部newmaxid
。 Promise.map()
被用于在假定的第二时间postStatus()
是异步的。 如果不是这样,尽管编写的代码可能略有不同,但是代码仍然可以正常工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.