拒绝不与承诺链在一起工作

时间:2017-01-26 17:19:28

标签: javascript angularjs promise

在我的应用中,我从USB设备接收包裹。发送命令后,我应该每N ms调用一次接收函数来获取所有数据包。

我用承诺创建了链:

var packagesCount = 10;
var chain = $q.when();
for (var i=0; i<packagesCount; i++) {
    chain = chain.then(hidRead((packagesCount-i)*1000));
}

chain.then(function () {
    console.log("all finished")
}, function (reason) {
    console.log(reason);
    console.log(reason)
});

我的read函数包含两个async函数:

function hidRead(ms) {
    var defer = $q.defer();

    setTimeout(function(){
        if (self.connectionId) {
            chrome.hid.receive(self.connectionId, function (reportId, data){
                console.log(data);
                defer.resolve();
            });
        } else {
            defer.reject(new Error('Connection failed'));
        }

    }, ms);

    return function() {
        return defer.promise;
    };
}

我的fail函数仅在完成所有Timeouts函数后调用。但我需要立即拒绝它。如果我们失去了连接并被拒绝,我们应该停止链执行。

我尝试添加catch,循环失败回调,任何帮助。

1 个答案:

答案 0 :(得分:0)

hidRead只是重新创建$timeout的功能,但问题是链创建时会调用hidRead,这意味着所有超时都将无条件执行。为避免这种情况,hidRead应返回回调函数。

如果chrome.hid.receive(...)不是异步或延迟绝不高于ms,则基本上类似于

function hidRead(ms) {
  return function () {
    return $timeout(function () {
      if (self.connectionId) {
        chrome.hid.receive(self.connectionId, function (reportId, data){
          console.log(data);
        });
      } else {
        return $q.reject(new Error('Connection failed'));
      }    
    });      
  }
}

否则,可能会另外使用$q.defer(),原始代码将更改为

function hidRead(ms) {
  return function () {
    var defer = $q.defer();
    setTimeout(...);
    return defer.promise;
  }
}

上面的代码将在每次迭代时触发摘要。如果没有必要或产生性能问题,$q可能会更改为原生Promise或Bluebird,后者具有Promise.delay,这在此类情况下非常有用。