NodeJS承诺:合并多个HTTP请求的正确方法返回

问题描述:

有一个NodeJS进程向达到Web服务的名为Kudos的东西。这些荣誉是从一个人发送给另一个人或一群人。我想要做的就是创建一个具有以下一个信息:NodeJS承诺:合并多个HTTP请求的正确方法返回


从{}海报以荣誉{接收机/ S}

{荣誉留言}


目前我有正确的工作过程,可以将一张海报发送给一个接收者我正在努力使它与获取接收器的多个名称一起工作。

问题源于这样的事实,即它返回接收荣誉的用户的部分,它只提供用户标识。所以我需要再打一次电话来获取用户名。我可以很容易地得到一个用户的承诺,但我似乎可以正确地获得多个用户。包含多个用户

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的指针都会非常有帮助。这真的是我的第一次刺痛,我希望我正朝着正确的方向前进。我知道我需要添加错误检查,但目前我只是想让这个进程为多个用户工作。

+0

您使用的是什么Node版本?还有什么Promise图书馆? '.each()'和'.done()'不是标准函数。 –

+0

_“我可以轻松获得为一位用户工作的承诺”_为每个用户重复该流程? – guest271314

+0

你有没有想过使用事件呢?每个“接收者”都可能触发一个可以完成工作的事件。 – ppovoski

如果您需要使用作为resolve函数的参数传递的承诺的结果,那么您可以在回调中捕获该结果。

如果你需要传递链的then方法中获得另一部分数据then你就必须归还,并抓住它通过onFulfilled回调以下then的。

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()总承诺。

你可以写Promise.all(array.map(mapper))但蓝鸟提供了更方便的Promise.map(array, mapper)

蓝鸟的.spread()也很方便,用于参考maxidkudos

这是简单形式,因为我可以管理:

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()是异步的情况下被第二次使用。如果情况并非如此,那么代码仍然可以工作,尽管它可能写法稍有不同。