如何获取通过过滤器的前N个Promise?

时间:2016-10-03 18:15:12

标签: javascript promise

如果我有一个值数组,并且我使用这些值来执行执行承诺的检查,那么如何获取通过检查的前N个Promise?

对于下面的例子,我只想要前面三个奇数,由函数isOdd确定,它返回一个promise。

const collection = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const len = collection.length;
const results = [];
let index = -1;

function isOdd(value) {
    if (value % 2 !== 0) {
        return Promise.resolve(1);
    } else {
        return Promise.resolve(0);
    }
}

while (++index < len) {
    const currentValue = collection[index];

    const result = isOdd(currentValue);

    // append the result to an array of results IF Promise.resolve's value === 1

    if (results.length >== 3) {
        break;
    }
}

Promise.all(results).then(doMoreStuff);

2 个答案:

答案 0 :(得分:3)

我正在重述这个问题,假设你提到的“过滤器”实际上是一个承诺被完成而被拒绝,而不是满足于0对1.换句话说:

function isOdd(value) {
  if (value % 2 !== 0) {
    return Promise.resolve();
  } else {
    return Promise.reject();
  }
}

你只需要编写逻辑。

function takeFirstN(promises, n) {
  const results = [];

  if (!promises.length) return Promise.resolve([]);

  return new Promise(resolve => {
    for (promise of promises) {
      promise.then(result => {
        results.push(result);
        if (!(--n)) resolve(results);
      });
    }
  });
}

换句话说,开始所有的承诺。当每个人结算时,将其结果放在结果列表中,并检查 n 承诺是否已解决,在这种情况下解决整体承诺。

然后:

const collection = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
takefirstN(collection.map(isOdd), 3)
  .then(results => console.log(results));

这不涉及小于 n 承诺的情况,或处理 n 等边缘情况大于承诺数的情况。这是一个练习。

原始问题

如果你想坚持使用值为0或1的promises定义,那么安排将谓词(在这里称为filter)传递给takeFirstNWhich函数,如下所示:

function takeFirstNWhich(promises, filter, n) {
  const results = [];

  if (!promises.length) return Promise.resolve([]);

  return new Promise(resolve => {
    for (promise of promises) {
      promise.then(result => {
        if (filter(result)) {
          results.push(result);
          if (!(--n)) resolve(results);
        }
      });
    }
  });
}

现在你可以写:

takefirstNWhich(collection.map(isOdd), odd => odd, 3)
  .then(results => console.log(results));

答案 1 :(得分:-1)

承诺没有阻止,因此当其他人完成时,没有真正的方法可以停止运行它们。我能想到的最接近的就是这样。

const collection = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const len = collection.length;
const results = [];
let index = -1;

function isOdd(value) {
    if (value % 2 !== 0) {
        return Promise.resolve(1);
    } else {
        return Promise.resolve(0);
    }
}

while (++index < len) {
    const currentValue = collection[index];

    if(results.length < 3) {
      isOdd(currentValue).then(
        function(result) {
          if(result == 1) {
            results.push(currentValue);
          }
        }
      );
    }
}

Promise.all(results).then(
  function() { 
    alert("done: " + results.join(', ');
  ); 
});

jsFiddle

但正如你所看到的那样,抓住了所有奇数值。您可以将if(results.length < 3)...移动到解析函数,但不会阻止它在每个元素上运行它返回的数量。