在循环内进行异步调用,直到找到一个值

Make asynchronous call inside loop until a value is found

我正在尝试在循环内多次调用异步 API,直到返回我想要的值(在本例中为 true)。问题是我不想在找到该值后继续循环,并且我不想在没有从它返回的值的情况下执行循环后的行......但到目前为止我无法让它工作。我想我在这里做错了什么,但是 "I can't get the whole picture".

function isSelected(element, callback) {
  // This is a little bit confusing for me...can I just get the value from
  // getDataAsync without using isSelected function?
  Office.select(element).getDataAsync(function (asyncResult) {
    var result = true;

    // some logic here that may change 'result'
    callback(result);
  });
}

function delete(elements) {
  var index = -1;

  for (var i = 0, (i < elements.length) && (index < 0); i++) {
    isSelected(elements[i], function(result) {
      if (result) { index = i; }; // ...and I don't want to keep "looping"
    });
  }
  // I want to execute these lines after the for-loop is done
  // ...do something with the "correct" index value
}

我推荐三种方法。

  • 仅使用 JavaScript.
  • 使用异步库。
  • 使用下划线库。

在这里您可以看到 javascript 实现:

你可以这样做: 你需要track home多次,你调用函数,回调发生了多少次

function delete(elements) {
  var index = -1;

  var stack=0;
  for (var i = 0, (i < elements.length) && (index < 0); i++) {
    stack++         // Go up on each loop
    isSelected(elements[i], function() {
      stack--;     //Go down each callback
      index = i;
      if(stack==0) afterAllFinish()   //When it return to 0 mean all callback have finished
    });
  }

  function afterAllFinish(){
    // I want to execute these lines after the for-loop is done
    // ...do something with the "correct" index value
  }
}

使用其他库:

  1. 下划线的解决方法请看http://underscorejs.org/#after

  2. 请查看https://github.com/caolan/async#parallel以了解异步解决方法。

你试过Kriskowal's Q了吗?有一个很好的函数叫做 Q#allSettled:

Q.allSettled(promises)
.then(function (results) {
    results.forEach(function (result) {
        if (result.state === "fulfilled") {
            var value = result.value;
        } else {
            var reason = result.reason;
        }
    });
});

所以基本上这就是它在您的情况下的工作方式:

var promises = [];

for(/* conditions */) {
  promises.push(/* async call which returns a promise */);
}

Q.allSettled(promises).then(function(results) {
    results.forEach(function (result) {
        var value;

        if (result.state === "fulfilled") {
            value = result.value;

            // do something with "value"
        }
    });
});

allSettled 只是确保 then 将被执行,无论承诺是否成功,您可以检查从异步调用中检索到的对象的值。