Функция .some () с использованием async и await всегда возвращает true - PullRequest
1 голос
/ 16 мая 2019

У меня есть класс JavaScript с некоторыми async функциями внутри.

Если в этом массиве число больше 10, я ожидаю, что функция .some() вернет true,но если массив не содержит чисел больше 10, я ожидаю, что он вернет false.

Проблема, с которой я сталкиваюсь, заключается в том, что вызов функции всегда возвращает true независимо от того, существует ли число больше 10в массиве.

class Blah {
    async doStuff() {
        const nums = [1, 2, 3, 4, 5, 6];
        const asyncResult = await nums.some(async num => {
            if (num > 10) {
                const allowed = await this.isAllowed(num);
                if (allowed) {
                    return true;
                }
            }
        });

        console.log(asyncResult);
    }

    async isAllowed(num) {
        console.log(`${num} is in the array`);
        return true;
    }
}

const b = new Blah();
b.doStuff(); // This return true but it should be returning false

В настоящее время возвращается true, но, как вы можете видеть, массив не имеет числа больше 10

Если я удаляю async извнутри функции .some() тогда, похоже, она работает, но эта функция должна быть async, потому что мне нужно await при вызове функции this.isAllowed, и это тоже функция async.

Ответы [ 3 ]

0 голосов
/ 16 мая 2019

.some синхронно.Когда ваша функция возвращает обещание (как и все асинхронные функции), .some воспринимает это как истинное значение.Таким образом, результат верен.

Если вы хотите разрешить все обещания, а затем проверить результаты, вы можете сделать это следующим образом:

async doStuff() {
  const nums = [1, 2, 3, 4, 5, 6];
  const promises = nums.map(async num => {
    if (num > 10) {
      const allowed = await this.isAllowed(num);
      if (allowed) {
        return true;
      }
    }
  });
  const areAllowed = await Promise.all(promises);
  const result = areAllowed.some(val => val);
  console.log(result);
}

Если они потенциально длинныевыполняя обещания, и вы хотите быть в состоянии выручить, как только любой из них преобразуется в истину, вы можете сделать это примерно так:

async doStuff() {
  const nums = [1, 2, 3, 4, 5, 6];
  const result = await new Promise(resolve => {
    let notAllowedCount = 0;
    nums.forEach(async num => {
      if (num > 10) {
        const allowed = await this.isAllowed(num);
        if (allowed) {
          // Found one that is allowed. Immediately resolve the outer promise
          resolve(true);
          return;
        }
      }
      // This one isn't allowed
      notAllowedCount++;
      if (notAllowedCount === nums.length) {
        // If we've reached the end, resolve to false. This will only happen
        //    if none of the earlier ones resolved it to true.
        resolve(false);
      }
    });
  });

  console.log(result);
}
0 голосов
/ 16 мая 2019

что-то вроде этого должно помочь (запустить фрагмент кода):

const isLGTen = async (n) => {
  await new Promise(resolve => setTimeout(resolve, 1000));
  
  return n > 10;
}


const someLGTen = nums => Promise
  .all(nums.map(isLGTen))
  .then(result => result.some(bool => bool));


(async () => {
  const data = [1, 2, 3, 4, 5, 11];

  console.log(
    `is some of "${data}" > "10"?`, 
    await someLGTen(data),
  );
})()
0 голосов
/ 16 мая 2019

Проблема:

Ваш обработчик some является функцией async.Асинхронные функции всегда возвращают обещания, которые считаются правдивыми.Например, !!new Promise(() => {}) === true.

Решение:

Вместо этого вы можете использовать Promise.all.Выполните итерацию по каждому num, если оно соответствует вашему условию, разрешите true в возвращаемом обещании.Если Promise.all завершено (т. Е. Вы проверили все числа) и возвращенное обещание еще не разрешено (т. Е. Ни одно из чисел не прошло ваше условие), тогда разрешите ложное (или отклоните) ваше обещание возврата.

class Blah {
  doStuff(nums) {
    return new Promise((resolve, reject) => {
      let promises = nums.map(async num => {
        if (num > 10 && await this.isAllowed(num))
          resolve(true);
      });
      Promise.all(promises).then(() => resolve(false));
    });
  }

  async isAllowed(num) {
    console.log(`${num} is in the array`);
    return true;
  }
}

const b = new Blah();

b.doStuff([1, 2, 3, 4, 5, 6]).then(value => console.log(value));

b.doStuff([1, 2, 3, 4, 5, 20]).then(value => console.log(value));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...