首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >节点承诺不向数组推送连续的嵌套响应。

节点承诺不向数组推送连续的嵌套响应。
EN

Stack Overflow用户
提问于 2017-07-18 07:34:43
回答 1查看 232关注 0票数 1

我正在使用AWS Node SDK执行以下任务-

  1. 获取区域
  2. 得到簇ARN的每个区域
  3. 获取ECS群集的筛选列表。
  4. 获取过滤群集的服务

我要退出的部分是步骤4,列出每个集群的服务。本质上是对每个集群列表服务的调用,每个响应只能返回10个项,因此函数被递归地调用,以查看是否有另一个页面令牌退出。每个响应被推送到一个数组中。然后是最后一个输出所有响应的Promise.all。问题是只捕获初始调用,而不捕获对下一个令牌的任何递归调用。如能提供任何帮助,将不胜感激:)

代码语言:javascript
复制
function getLiveCluster() {

  var liveClusterName = 'xx1-app-ecs'

  // Filter out the required clusters
  clustersAry.forEach(function(cluster) {
    if (cluster && cluster.clusterArns && cluster.clusterArns.length > 0) {
      cluster.clusterArns.forEach(function(clusterArns) {
        if (clusterArns.indexOf(liveClusterName) > -1) {

          var serviceParams = {
            cluster: clusterArns,
            maxResults: 10,
            nextToken: ''
          };

          ecsRegionParams.region = cluster.RegionName;
          ecs = new aws.ECS(ecsRegionParams);
          getClusterServices(serviceParams)
        }
      });
    }
  });

  Promise.all(promiseAry2).then(() => {
    console.log('All services <<<<<<<<<<<<\n', serviceAry)
  });
}

function getClusterServices(serviceParams) {

  promiseAry2.push(ecs.listServices(serviceParams).promise().then(function(data) {

    serviceAry.push({
      cluster: serviceParams.cluster,
      service: data.serviceArns
    });

    if (data.nextToken) {
      serviceParams.nextToken = data.nextToken;
      getClusterServices(serviceParams)
    }
  }).catch((err) => {}));
}

编辑1

调试Promise.all数组后,仍有一些承诺尚未兑现,请参见-

代码语言:javascript
复制
"> All promiseAry2 <<<<<<<<<<<<
 [ Promise { undefined },
  Promise { undefined },
  Promise { undefined },
  Promise { undefined },
  Promise { undefined },
  Promise { undefined },
  Promise { undefined },
  Promise { <pending> },
  Promise { <pending> },
  Promise { <pending> },
  Promise { <pending> } ]"

有什么办法确保承诺完成吗?

答复1

谢谢--这是一段类代码,只需一周就能很好地工作。如图所示,ECS的区域需要重新设置-

代码语言:javascript
复制
// Reset ECS to current cluster region
ecsRegionParams.region = cluster.RegionName;

// Store the request for this cluster as a promise
promiseAry.push(
    getClusterServices(
        new aws.ECS(ecsRegionParams),
        serviceParams
    )
)

新输出以单独的对象传回数据,如下所示-

代码语言:javascript
复制
All arrayOfarraysOfServices <<<<<<<<<<<<
[ [ { cluster: 'arn:aws:ecs:eu-central-1:0123456789:cluster/xx1-app-ecs-ECSCluster-1',
service: 
[ 'arn:aws:ecs:eu-central-1:0123456789:service/service-1',
'arn:aws:ecs:eu-central-1:0123456789:service/service-2',
'arn:aws:ecs:eu-central-1:0123456789:service/service-3',
'arn:aws:ecs:eu-central-1:0123456789:service/service-4',
'arn:aws:ecs:eu-central-1:0123456789:service/service-5',
'arn:aws:ecs:eu-central-1:0123456789:service/service-6',
'arn:aws:ecs:eu-central-1:0123456789:service/service-7',
'arn:aws:ecs:eu-central-1:0123456789:service/service-8',
'arn:aws:ecs:eu-central-1:0123456789:service/service-9',
'arn:aws:ecs:eu-central-1:0123456789:service/service-10' ] },
{ cluster: 'arn:aws:ecs:eu-central-1:0123456789:cluster/xx1-app-ecs-ECSCluster-1',
service: 
[ 'arn:aws:ecs:eu-central-1:0123456789:service/service-11',
'arn:aws:ecs:eu-central-1:0123456789:service/service-12' ] } ],
[ { cluster: 'arn:aws:ecs:eu-central-1:0123456789:cluster/xx1-app-ecs-ECSCluster-2',
service: 
[ 'arn:aws:ecs:eu-central-1:0123456789:service/service-1',
'arn:aws:ecs:eu-central-1:0123456789:service/service-2',
'arn:aws:ecs:eu-central-1:0123456789:service/service-3',
'arn:aws:ecs:eu-central-1:0123456789:service/service-4',
'arn:aws:ecs:eu-central-1:0123456789:service/service-5',
'arn:aws:ecs:eu-central-1:0123456789:service/service-6',
'arn:aws:ecs:eu-central-1:0123456789:service/service-7',
'arn:aws:ecs:eu-central-1:0123456789:service/service-8',
'arn:aws:ecs:eu-central-1:0123456789:service/service-9',
'arn:aws:ecs:eu-central-1:0123456789:service/service-10' ] },
{ cluster: 'arn:aws:ecs:eu-central-1:0123456789:cluster/xx1-app-ecs-ECSCluster-2',
service: 
[ 'arn:aws:ecs:eu-central-1:0123456789:service/service-11',
'arn:aws:ecs:eu-central-1:0123456789:service/service-12' ] } ],
[ { cluster: 'arn:aws:ecs:eu-central-1:0123456789:cluster/xx1-app-ecs-ECSCluster-3',
service: 
[ 'arn:aws:ecs:eu-central-1:0123456789:service/service-1',
'arn:aws:ecs:eu-central-1:0123456789:service/service-2',
'arn:aws:ecs:eu-central-1:0123456789:service/service-3' ] } ],
[ { cluster: 'arn:aws:ecs:eu-central-1:0123456789:cluster/xx1-app-ecs-ECSCluster-4',
service: [] } ],
[ { cluster: 'arn:aws:ecs:eu-central-1:0123456789:cluster/xx1-app-ecs-ECSCluster-5',
service: [] } ]]

接下来我要做的是过滤推送,以便如果集群arn已经存在,那么数据就会连接到现有条目。

例如,集群arn:aws:ecs:eu-central-1:0123456789:cluster/xx1-app-ecs-ECSCluster-1有12个服务,而不是有2个对象,它将有一个带有12个服务。

在函数getClusterServices中这样做是明智的,还是应该在Promise.all中完成所有承诺之后再这样做呢?

编辑2

这里有一种解决方案,可以将数组的数组变回单数数组,找到重复的,将重复的集群服务附加到当前的集群服务中,然后删除最后分页的集群服务数组duplicate...producing。

代码语言:javascript
复制
Promise.all(promiseAry).then((arrayOfarraysOfServices) => {

    // Consolidate data into singular array
    var singularAry = [];

    // Recursively print array of unknown dimensions
    function morphToSingularArray(arr) {
        for (var i = 0; i < arr.length; i++) {
            if (arr[i] instanceof Array) {
                morphToSingularArray(arr[i]);
            } else {
                singularAry.push(arr[i]);
            }
        }
        return singularAry;
    }

    var listAry = morphToSingularArray(arrayOfarraysOfServices);

    // Merge services for duplicate clusters
    // First cluster in array
    for (var i = 0; i < listAry.length; ++i) {
        // Second cluster in array
        for (var j = i + 1; j < listAry.length; ++j) {
            // Matching
            if (listAry[i].cluster === listAry[j].cluster) {
                // Does service object exist
                if (listAry[j].service && listAry[j].service.length > 0) {
                    var serviceAry = listAry[j].service;
                    // Iterate over second cluster services, appending to first cluster services
                    for (var x = 0; x < serviceAry.length; ++x) {
                        listAry[i].service.push(serviceAry[x]);
                    }
                }
                // Delete second cluster after appending
                listAry.splice(j--, 1);
            }
        }
    }
    console.log('Paginated data array\n', listAry)

}).catch((e) => console.log(e));

映射是否可用作上述三份数组解决方案的清洁方法?

EN

回答 1

Stack Overflow用户

发布于 2017-07-18 16:14:44

下面是您的问题,您正在将承诺传递到一系列承诺中,然后在数组已经传递到Promise.all之后,每个承诺本身都有可能将更多的承诺推入同一个数组。

在这样的回调中创建承诺,同时在全球维护所有数据,这是一个众所周知的用承诺反模式

承诺解决一个值,并可以被链接,这意味着我们通常可以通过它们传播他们的结果,而不是拥有全局数据。

在我看来,您想要,对于clustersAry中的每个元素,获取它的服务(如果它们存在的话),对于每个服务,递归地获取它们的服务等等。

您应该让getClusterServices本身返回一个通过递归级别收集到的服务数组中解析的承诺。

以下是基于上述评论的一种方法:

代码语言:javascript
复制
function getLiveCluster() {

  const liveClusterName = 'xx1-app-ecs'

  // Filter out the required clusters
  clustersAry.forEach(cluster => {
    if (cluster && cluster.clusterArns && cluster.clusterArns.length > 0) {
      cluster.clusterArns.forEach(clusterArns => {
        if (clusterArns.indexOf(liveClusterName) > -1) {
          const serviceParams = {
            cluster: clusterArns,
            maxResults: 10,
            nextToken: ''
          };

          // store the request for this cluster as a promise
          promiseAry.push(
            getClusterServices(
              new aws.ECS(cluster.RegionName),
              serviceParams
            )
          )
        }
      });
    }
  });

  Promise.all(promiseAry).then((arrayOfarraysOfServices) => {
    console.log('All services <<<<<<<<<<<<\n', arrayOfarraysOfServices)
  });
}

function getClusterServices(ecs, serviceParams, clusterServiceAry = []) {
  // return a promise here that resolves 
  // with an array of services for the given serviceParams
  // once all recursive service requests are finished
  return ecs
    .listServices(serviceParams)
    .promise()
    .then(data => {
      clusterServiceAry.push({
        cluster: serviceParams.cluster,
        service: data.serviceArns
      });

      return !data.nextToken
        ? clusterServiceAry  // nextToken is falsy, we are finished, resolve with the service array
        : getClusterServices(
            ecs,
            // update the token by creating a new object
            // rather than mutating the existing one
            Object.assign(
              {},
              serviceParams,
              {
                nextToken: data.nextToken
              }
            ),
            // pass the cluster service array so we can accumulate
            // the services
            clusterServiceAry
          )
      })
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45160357

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档