Javascript NodeJS:如何处理并行运行的可变数量的回调,并将它们的响应映射到请求?

Javascript NodeJS:如何处理并行运行的可变数量的回调,并将它们的响应映射到请求?,javascript,node.js,amazon-web-services,express,Javascript,Node.js,Amazon Web Services,Express,为了让自己更多地了解node js,我开始使用aws sdk为SimpleDB(sdb)制作一个基本的CRUD REST服务器 在我找到读取域的函数之前,一切都很顺利。为此,aws sdk有两个功能:和。listDomains返回sdb域名数组。domainMetadata将返回有关域的其他统计信息,但一次只返回一个域的统计信息。结果中不包括域名 我的脚本正在运行listDomains,并在JSON响应中返回一个数组。不过,我想让我的api readDomains函数更加雄心勃勃,让它在同一个a

为了让自己更多地了解node js,我开始使用aws sdk为SimpleDB(sdb)制作一个基本的CRUD REST服务器

在我找到读取域的函数之前,一切都很顺利。为此,aws sdk有两个功能:和。listDomains返回sdb域名数组。domainMetadata将返回有关域的其他统计信息,但一次只返回一个域的统计信息。结果中不包括域名

我的脚本正在运行listDomains,并在JSON响应中返回一个数组。不过,我想让我的api readDomains函数更加雄心勃勃,让它在同一个api调用中返回所有域的元数据。毕竟,同时运行几个domainMetadata调用是节点的异步io应该发挥作用的地方

问题是我不知道如何运行可变数量的调用,如何对所有调用使用相同的回调,如何将每个domainMetadata调用的结果与它的domainName匹配(因为它是异步的,并且它们不保证按请求的顺序返回)并告知所有元数据请求何时完成,以便发送最终响应。在代码中,我的问题是:

domain.receiveDomainList = function(err, data){
 var domainList = [];

 for(var i=0; i<data.DomainNames.length; i++){
   sdb.domainMetaData({"DomainName":data.DomainNames[i]},domain.receiveMetadata);
   // alternatively:   domainList.push({"DomainName":data.DomainNames[i]});
 }
 // alternatively:  
 // async.map(domainList, sdb.domainMetadata, domain.receiveMetadata)

 console.log(domainList);
}

domain.receiveMetadata = function (err, data){
  // I figure I can stash the results one at a time in an array in the
  // parent scope but...

  // How can I tell when all of the results have been received?

  // Since the domainname used for the original call is not returned with 
  // the results how do I tell what result matches what request?
}
domain.receiveDomainList=函数(错误,数据){
var domainList=[];
对于(var i=0;i使用,您可以设置上下文或
值,并为绑定函数提供前导默认参数

下面的示例代码纯粹是为了说明如何使用
.bind()
为响应回调添加额外的上下文

在下面的代码中,
.bind
用于:

  • domainResults
    对象设置为
    receiveMetaData
    回调的上下文
  • 将当前域名作为参数传递给回调函数
domainResults
对象用于:

  • 跟踪第一次请求中收到的姓名数量
  • 跟踪completedCount(在元数据请求的每次回调中递增)
  • 跟踪列表中的错误和成功响应
  • 提供完整的回调
完全未经测试的代码仅用于说明目的:

domain.receiveDomainList = function(err, data) {
    // Assuming err is falsey
    var domainResults = {
        nameCount: data.DomainNames.length,
        completeCount: 0,
        list: {},
        complete: function() {
            console.log(this.list);
        }
    };

    for (var i = 0; i < data.DomainNames.length; i++) {
        sdb.domainMetaData({ "DomainName": data.DomainNames[i] },
                             domain.receiveMetadata.bind(domainResults, data.DomainNames[i]));
    }
}

domain.receiveMetadata = function(domainName, err, data) {
    // Because of .bind, this === domainResults
    this.completeCount++;
    this.list[domainName] = data || {error: err};

    if(this.completeCount === this.nameCount) {
        this.complete();
    }
}
domain.receiveDomainList=函数(错误,数据){
//假设错误是错误的
var domainResults={
nameCount:data.DomainNames.length,
完成计数:0,
列表:{},
完成:函数(){
console.log(this.list);
}
};
对于(var i=0;i
使用,您可以设置上下文或
值,并为绑定函数提供前导默认参数

下面的示例代码纯粹是为了说明如何使用
.bind()
为响应回调添加额外的上下文

在下面的代码中,
.bind
用于:

  • domainResults
    对象设置为
    receiveMetaData
    回调的上下文
  • 将当前域名作为参数传递给回调函数
domainResults
对象用于:

  • 跟踪第一次请求中收到的姓名数量
  • 跟踪completedCount(在元数据请求的每次回调中递增)
  • 跟踪列表中的错误和成功响应
  • 提供完整的回调
完全未经测试的代码仅用于说明目的:

domain.receiveDomainList = function(err, data) {
    // Assuming err is falsey
    var domainResults = {
        nameCount: data.DomainNames.length,
        completeCount: 0,
        list: {},
        complete: function() {
            console.log(this.list);
        }
    };

    for (var i = 0; i < data.DomainNames.length; i++) {
        sdb.domainMetaData({ "DomainName": data.DomainNames[i] },
                             domain.receiveMetadata.bind(domainResults, data.DomainNames[i]));
    }
}

domain.receiveMetadata = function(domainName, err, data) {
    // Because of .bind, this === domainResults
    this.completeCount++;
    this.list[domainName] = data || {error: err};

    if(this.completeCount === this.nameCount) {
        this.complete();
    }
}
domain.receiveDomainList=函数(错误,数据){
//假设错误是错误的
var domainResults={
nameCount:data.DomainNames.length,
完成计数:0,
列表:{},
完成:函数(){
console.log(this.list);
}
};
对于(var i=0;i
签出承诺或libraryQ和其他承诺连续运行,因此我失去了节点异步设置的巨大好处。我尝试了async.map,但没有成功。正如我提到的,它导致aws sdk中出现错误。async.parallel需要使用静态函数调用编写,因此无法处理可变数量的调用。如果我错了,您能提供一个s吗在此上下文中有足够的调用可以工作吗?您可以创建大量并行运行承诺,然后使用等待它们的结果。对于
Q.all
,您可以传递带有任意数量任务的数组。签出承诺或libraryQ和其他承诺连续运行,这样我就失去了节点异步设置的巨大好处。我尝试了async.map不走运。正如我提到的,它在aws sdk中导致了一个错误。async.parallel需要使用静态函数调用编写,因此无法处理数量可变的调用。如果我错了,您能否在此上下文中提供一个可以工作的示例调用?您可以创建大量并行运行承诺,然后使用。等待结果
Q.all
并且您可以传递包含任意数量任务的数组