首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用返回承诺的函数过滤数组

使用返回承诺的函数过滤数组
EN

Stack Overflow用户
提问于 2015-10-26 21:00:29
回答 17查看 107.7K关注 0票数 96

给定的

代码语言:javascript
运行
复制
let arr = [1,2,3];

function filter(num) {
  return new Promise((res, rej) => {
    setTimeout(() => {
      if( num === 3 ) {
        res(num);
      } else {
        rej();
      }
    }, 1);
  });
 }

 function filterNums() {
   return Promise.all(arr.filter(filter));
 }

 filterNums().then(results => {
   let l = results.length;
   // length should be 1, but is 3
 });

长度为3,因为返回的是承诺,而不是值。是否有一种方法可以使用返回承诺的函数对数组进行筛选?

注意:对于这个示例,fs.stat已被setTimeout替换,有关具体代码,请参见https://github.com/silenceisgolden/learn-esnext/blob/array-filter-async-function/tutorials/array-filter-with-async-function.js

EN

回答 17

Stack Overflow用户

回答已采纳

发布于 2015-10-27 08:25:19

正如注释中提到的,Array.prototype.filter同步的,因此不支持承诺。

由于您现在(理论上)可以使用ES6构建子类类型,所以您应该能够添加自己的异步方法,该方法封装了现有的过滤器函数:

注意:我已经注释掉了子类,因为Babel还不支持数组

代码语言:javascript
运行
复制
class AsyncArray /*extends Array*/ {
  constructor(arr) {
    this.data = arr; // In place of Array subclassing
  }

  filterAsync(predicate) {
     // Take a copy of the array, it might mutate by the time we've finished
    const data = Array.from(this.data);
    // Transform all the elements into an array of promises using the predicate
    // as the promise
    return Promise.all(data.map((element, index) => predicate(element, index, data)))
    // Use the result of the promises to call the underlying sync filter function
      .then(result => {
        return data.filter((element, index) => {
          return result[index];
        });
      });
  }
}
// Create an instance of your subclass instead
let arr = new AsyncArray([1,2,3,4,5]);
// Pass in your own predicate
arr.filterAsync(async (element) => {
  return new Promise(res => {
    setTimeout(() => {
      res(element > 3);
    }, 1);
  });
}).then(result => {
  console.log(result)
});

Babel REPL Demo

票数 47
EN

Stack Overflow用户

发布于 2017-10-20 03:58:51

下面是一个使用异步/等待的2017年优雅解决方案:

非常简单的用法:

代码语言:javascript
运行
复制
const results = await filter(myArray, async num => {
  await doAsyncStuff()
  return num > 2
})

助手函数(将其复制到您的网页):

代码语言:javascript
运行
复制
async function filter(arr, callback) {
  const fail = Symbol()
  return (await Promise.all(arr.map(async item => (await callback(item)) ? item : fail))).filter(i=>i!==fail)
}

演示:

代码语言:javascript
运行
复制
// Async IIFE
(async function() {
  const myArray = [1, 2, 3, 4, 5]

  // This is exactly what you'd expect to write 
  const results = await filter(myArray, async num => {
    await doAsyncStuff()
    return num > 2
  })

  console.log(results)
})()


// Arbitrary asynchronous function
function doAsyncStuff() {
  return Promise.resolve()
}


// The helper function
async function filter(arr, callback) {
  const fail = Symbol()
  return (await Promise.all(arr.map(async item => (await callback(item)) ? item : fail))).filter(i=>i!==fail)
}

我甚至还会加一个CodePen

票数 82
EN

Stack Overflow用户

发布于 2018-11-27 21:36:39

对于类型记录(或者es6只是删除类型语法)

代码语言:javascript
运行
复制
function mapAsync<T, U>(array: T[], callbackfn: (value: T, index: number, array: T[]) => Promise<U>): Promise<U[]> {
  return Promise.all(array.map(callbackfn));
}

async function filterAsync<T>(array: T[], callbackfn: (value: T, index: number, array: T[]) => Promise<boolean>): Promise<T[]> {
  const filterMap = await mapAsync(array, callbackfn);
  return array.filter((value, index) => filterMap[index]);
}

es6

代码语言:javascript
运行
复制
function mapAsync(array, callbackfn) {
  return Promise.all(array.map(callbackfn));
}

async function filterAsync(array, callbackfn) {
  const filterMap = await mapAsync(array, callbackfn);
  return array.filter((value, index) => filterMap[index]);
}

es5

代码语言:javascript
运行
复制
function mapAsync(array, callbackfn) {
  return Promise.all(array.map(callbackfn));
}

function filterAsync(array, callbackfn) {
  return mapAsync(array, callbackfn).then(filterMap => {
    return array.filter((value, index) => filterMap[index]);
  });
}

编辑:演示

代码语言:javascript
运行
复制
function mapAsync(array, callbackfn) {
  return Promise.all(array.map(callbackfn));
}

function filterAsync(array, callbackfn) {
  return mapAsync(array, callbackfn).then(filterMap => {
    return array.filter((value, index) => filterMap[index]);
  });
}

var arr = [1, 2, 3, 4];

function isThreeAsync(number) {
  return new Promise((res, rej) => {
    setTimeout(() => {
      res(number === 3);
    }, 1);
  });
}

mapAsync(arr, isThreeAsync).then(result => {
  console.log(result); // [ false, false, true, false ]
});

filterAsync(arr, isThreeAsync).then(result => {
  console.log(result); // [ 3 ]
});

票数 33
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33355528

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档