首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Highland.js中的上下文

Highland.js中的上下文
EN

Stack Overflow用户
提问于 2015-03-17 19:50:10
回答 2查看 331关注 0票数 2

我喜欢Highland.js和一般的反应式编程风格。我正在为失去上下文而挣扎,我正在努力确定如何在一个目标是放弃状态的模型中优雅地处理上下文。

例如,我在中有一个帐户数组。

代码语言:javascript
复制
var accounts = [{accessId:"12345","secretKey":"abc123","account":"foo"},
                {accessId:"34512","secretKey":"def456","account":"bar"}];

我的目标基本上是创建运行在某个区域中的所有EC2实例的电子表格。就像这样。

代码语言:javascript
复制
Account   | Instance Size
--------- | -------------
foo       | m3.xlarge
foo       | c3.medium
bar       | t2.small

一般的工作流程是

  1. 检查每一个帐户
  2. 调用ec2DescribeInstaces
  3. 以某种方式将每个ec2DescribeInstances调用映射回帐户名以进行最终输出

在普通的JavaScript中,我们将在这里循环,所以每次调用ec2DescribeInstances时,都会存在一个上下文

代码语言:javascript
复制
for ( account in accounts ) {
  var instances = ec2DescribeInstaces(account);
  for ( instance in instances ) {
    results.push({account:account.name, instanceSize: instance.size});
  }
}

根据我对反应性编程的理解,我会这样做

代码语言:javascript
复制
_(accounts)
 .map(ec2DescribeInstaces)
 .parallel(2)
 .each(function(result) {
   results.push(result);
 });

有指引吗?在这条链的末尾,我看到了亚马逊的例子。但我不知道怎么把这些和账户联系起来才能知道名字。我知道我可以绕过这些来获得价值,但我正在寻找最佳实践和一些优雅的东西。

所以@Bergi,就像下面这样?这将返回一个“上下文”对象,除了从Amazon返回的数据之外,还包含我需要的两个数据。我唯一关心的是,如果我在整个链中传递一个上下文,那么我们将为调用做大量的数据提取、填充和包装。

代码语言:javascript
复制
ec2DescribeInstances = _.wrapCallback(function(accountData, callback) {
  // we remove the extraneous account name using a pick
  var ec2 = new AWS.EC2(lodash.pick(accountData,'accessKeyId','secretAccessKey'));
  ec2.describeInstances({ Filters: [{Name:'instance-state-name', Values:['running']}] }, function(err,data) {
    if ( err ) return callback(err);
    // here I create an object that wraps the AWS response
    callback(null, {"account":accountData.alias, "data": data})
  });
});
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-03-17 20:17:32

您可以使用_.zip(),它接受两个流并返回成对的流。因此,以生成ec2Instances的流为例:

代码语言:javascript
复制
var ec2InstanceStream = _(accounts)
    .map(ec2DescribeInstaces)
    .parallel(2);

_(acounts).zip(ec2InstanceStream);
    .each(function(result) {
        //Each result: [{ /* original account */ }, { /* ec2 instance */ }]
        results.push(result);
    });

所以现在你把一切都放在一起了。你当然可以做得更好。例如,如果要将每一对对象合并为单个对象,可以在.each()步骤之前添加一个.each(),以便将这些对象合并在一起。

票数 1
EN

Stack Overflow用户

发布于 2016-09-21 01:06:00

我会嵌套这些操作以获得一些范围:

代码语言:javascript
复制
const h = require("highland");
const ec2DescribeInstaces = h.wrapCallback(function(account, cb) {
  return cb(null, [{
    size: account.size
  }, {
    size: ++account.size
  }]);
});

const accounts = [{
  size: 1, name: 1
}, {
  size: 2, name: 2
}, {
  size: 3, name: 3
}];

var results = [];
h(accounts)
  .map(account => {
    return ec2DescribeInstaces(account)
      .flatten()
      .map(instance => ({
        account: account.name,
        instanceSize: instance.size,
      }));
  })
  .parallel(2)
  .tap(results.push.bind(results))
  .collect()
  .toCallback(h.log)

通过这种方式,您仍然了解每个instance在处理该实例时与之相关的单个instance,而且由于map的结果是一个流,所以流仍然将并行运行。

此外,我认为这是一个广泛适用的方法。无论您返回了多少个实例,或者您想为每个帐户做多少事情都无关紧要。例如,如果您需要为帐户上的每个实例将两个值推送到parallel(2),您可以从map返回两个流,并且您不需要完全调整您的方法,只需要调整行为。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29108401

复制
相关文章

相似问题

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