当前位置: 首页 > 知识库问答 >
问题:

bluebirdjspromise封装在for循环中

阎璞瑜
2023-03-14

我有一堆函数用来向我的服务提供数据。我想循环遍历它们中的每一个,并在其中一个返回所需结果时立即停止。如果第一个工作,那很好。如果它有异常或数据无效,我想移动到下一个等等。

我该如何实现这一点?我有下面的代码:

handleData: function(address) {
  var self = this;
  return new Promise(function (resolve, reject) {
    for (var i = 0; i < self.listAllAvailableProviders.length; ++i) {
      var handler = self.listAllAvailableProviders[i];
      new handler().getData(address)
        .then(function(value) {
          Logger.info(value);
          resolve(value);
        })
        .catch(function(err){
          Logger.error(err);
        })
    }
    reject("");
  });
}

如何修复它,使其在第一个获得正确数据后立即停止?我已经通读了bluebirdjs文档,但没有结果。

编辑:我把一个突破语句放在解决之后,我得到了这个:

SyntaxError: Illegal break statement
at Object.exports.runInThisContext (vm.js:53:16)
at Module._compile (module.js:513:28)
at Object.Module._extensions..js (module.js:550:10)
at Module.load (module.js:458:32)
at tryModuleLoad (module.js:417:12)
at Function.Module._load (module.js:409:3)
at Module.require (module.js:468:17)
at require (internal/module.js:20:19)

共有2个答案

蓬威
2023-03-14

如果promise不是硬约束,那么caolan/async#eachSeries或类似产品可能会有所帮助。类似于。。。

// var Promise = require(?)
// var async = require("async")
handleData: asyncProviderFinder

...

function asyncProviderFinder(address){
  var self = this;
  return new Promise(function(resolve, reject){
    async.eachSeries(
      self.listAllAvailableProviders, 
      function iterate(provider, next){
        var handler = provider;
        new handler().getData(address)
        .then( function(value){
          Logger.info(value);
          next("abort"); // callback any error to abort future iterations
          return resolve(value);
        })
        .catch( function (err){
          Logger.error(err);
          next();
        });
      },
      function callback(err, firstProvider){
        if ((firstProvider === undefined) && !err ){ reject(""); }
      }
    );
  });
}
刘翔宇
2023-03-14

您正在for循环中并行运行所有请求,因此当您找到一个具有您喜欢的值的请求时,其他请求已经启动,因此无法“不”运行它们。如果你不想在找到一个后再运行其他的,你就不需要同时启动它们。因此,这将引导您进入一个设计模式,在该模式中序列化请求。运行一个,如果不成功,运行下一个,依此类推。

据我所知,蓝鸟并没有一个内置的计划来满足你的要求。我能想到的最简单的事情是使用Bluebird中的一个数组处理函数,该函数将一个接一个地序列化请求,例如Promise.mapSeries(),然后在找到合适的值时使用拒绝来中止处理。

handleData: function(address) {
    return Promise.mapSeries(this.listAllAvailableProviders, function(handler) {
        return new handler().getData(address).then(function(value) {
            // the first success we get, we will throw with 
            // the returned value in order to stop the .mapSeries progression
            throw value;
        }, function(err) {
            // log the error, but don't let the rejection propagate so other handlers are called
            Logger.error(err);
        })
    }).then(function() {
        // nothing succeeded here, turn it into an overall rejection
        throw new Error("No getData() handlers succeeded");        
    }, function(val) {
        // reject here means we got a good value so turn it into a resolved value
        return val;
    })
}


// usage
obj.handleData().then(function(val) {
    // got value here
}).catch(function(err) {
    // no values here
});

奇怪的是,如果您自己迭代处理程序,它似乎代码更少,而且可能更简单:

handleData: function(address) {
    var index = 0;
    var handlers = this.listAllAvailableProviders;
    var handlerCnt = handlers.length;

    function next() {
        if (index < handlerCnt) {
            var handler = handlers[index++];
            return new handler().getData(address).catch(next);
        } else {
            return Promise.reject(new Error("No handler found for address"));
        }
    }
    return next();
}
 类似资料:
  • 问题内容: 我试图在for循环内发出几个服务器请求。我发现了[\这个问题,\并实施了建议的解决方案。但是,它似乎不起作用。 如果我删除了for循环并将所有xmlhttp [i]更改为xmlhttp,那么对于一个元素来说一切都很好,但是我无法发出多个请求。在此先感谢您的任何建议。 问题答案: 尝试下面的代码段 响应

  • 我试图在for循环中获得for循环,因此输出如下: 我希望输出显示一个正方形 我不知道它为什么不这样做。下面是我的代码:

  • for循环是一种重复控制结构,允许您有效地编写需要执行特定次数的循环。 语法 (Syntax) Perl编程语言中for循环的语法是 - for ( init; condition; increment ) { statement(s); } 这是for循环中的控制流 - init步骤首先执行,只执行一次。 此步骤允许您声明和初始化任何循环控制变量。 只要出现分号,就不需要在此处输入声明。

  • ' for '循环是最紧凑的循环形式。 它包括以下三个重要部分 - loop initialization ,我们将计数器初始化为起始值。 初始化语句在循环开始之前执行。 test statement将测试给定条件是否为真。 如果条件为真,则执行循环内给出的代码,否则控件将退出循环。 iteration statement ,您可以在其中增加或减少计数器。 您可以将所有三个部分放在一行中以分号分隔

  • 问题 你想通过一个 for 循环来迭代数组、对象或范围。 解决方案 # for(i = 1; i<= 10; i++) x for x in [1..10] # => [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ] # To count by 2 # for(i=1; i<= 10; i=i+2) x for x in [1..10] by 2 # => [ 1, 3, 5,

  • for循环是一种重复控制结构,允许您有效地编写需要执行特定次数的循环。 语法 (Syntax) Objective-C编程语言中for循环的语法是 - for( init; condition; increment ) { statement(s); } 这是for循环中的控制流 - init步骤首先执行,只执行一次。 此步骤允许您声明和初始化任何循环控制变量。 只要出现分号,就不需要在此