Коротка відповідь
juniorАсинхронний filter — це метод, що приймає async callback і повертає новий масив з елементами, для яких колбек повернув true. Реалізується через Promise.all: викликаємо callback для всіх елементів, чекаємо результат і фільтруємо. Приклад: const res = await Promise.all(arr.map(async (v,i)=>({ok:await fn(v,i), val:v}))); return res.filter(o=>o.ok).map(o=>o.val);
Повне пояснення
Що це і навіщо
Асинхронний filter дозволяє виконувати асинхронні перевірки (наприклад, запити до API) для кожного елемента масиву і збирати лише ті, що відповідають умові.
Принцип роботи / алгоритм
- Для кожного елемента викликаємо async callback, що повертає
true/falseабо Promise. - Збираємо всі проміси в масив і чекаємо їх завершення через
Promise.all. - Після отримання результатів фільтруємо оригінальний масив за відповідними значеннями.
Реалізація (JS / TS)
async function asyncFilter(arr, fn) {
const results = await Promise.all(arr.map((v,i)=>fn(v,i)));
return arr.filter((_v,i)=>results[i]);
}
Тестування
import { test, expect } from 'vitest';
test('asyncFilter', async () => {
const res = await asyncFilter([1,2,3], async n=>n%2===0);
expect(res).toEqual([2]);
});
Проблеми та edge cases
- Порядок елементів –
Promise.allзберігає порядок, тому фільтрація працює коректно. - Помилки у callback – обгорнути в
try/catchабо використовувати.catch(()=>false). - Великий масив – може перевантажити стек; розбивайте на батчі.
- Синхронний callback – працює, бо
Promise.allприймає значення. - Паралельні запити – якщо API обмежує кількість одночасних, використайте throttling.
Оптимізація та продуктивність
- Використовуйте
for-await-ofз генератором, щоб обробляти елементи по черзі. - Для великих масивів застосуйте
p-limitабо власний батчинг.
Без JS / архітектурні альтернативи
- Якщо перевірка може бути синхронною, використайте звичайний
Array.prototype.filter. - Для простих умов можна застосувати CSS селектори (
:nth-child) або серверну фільтрацію.
Cheatsheet + follow-up
- Корисно знати:
Array.prototype.flatMapможна комбінувати з asyncFilter для одновременої трансформації. - Потенційне інтерв’ю: Як обробити помилки у asyncFilter? Чому
Promise.allзберігає порядок елементів?