使用异步过滤和映射 Promise
Posted
技术标签:
【中文标题】使用异步过滤和映射 Promise【英文标题】:Filter and map Promise with async 【发布时间】:2020-06-16 22:01:36 【问题描述】:我得到了由 sequelize.findAndCountAll() 返回的 promise 对象,我想在映射之前过滤对象。
这是我的代码:
async function getCountTask(id)
return await Tasks.count(
where:
studentID: id,
status: 'Done',
grade: ['A', 'B']
);
let totalStudent = [];
await Promise.all(
listStudent.filter(async (f) =>
const count = await getCountTask(f.id);
if(count <= 3)
return false;
return true;
).map(async (e) =>
let obj = ;
obj.id = e.id;
obj.age = e.age;
obj.status = 'Great';
totalStudent.push(obj);
)
)
我的期望 listStudent 包含 5 个数据,但过滤后它只会包含 3 个数据,因为另外 2 个没有通过条件。因此,对于最终结果,totalStudent 包含 3 个数据。
但我从上面的代码中得到的是,totalStudent 的数据与 listStudent 完全相同。 这是因为它先处理地图然后过滤,所以地图处理尚未过滤的数据。
如何让它先成为过滤器,然后再映射数据。
提前致谢。
【问题讨论】:
您不是在使用.map
进行映射操作,而是在进行简单的迭代。但我很困惑——listStudent
是什么?它是一系列承诺吗?一个承诺?如果是这样,您必须先await
(或使用 Promise API)或使用Promise.all
,然后才能过滤/映射。如果listStudent
不是一个承诺,我不确定这段代码在做什么。过滤和映射实际上不适用于 async
函数。
listStudent 是一个 promise 对象,它是从 sequelize 返回的。我在上面做了await Promise.all()
。或者你的意思是像const lStudent = await Promise.all(listStudent);
然后映射lStudent?它也不起作用
filter(async (f)
不会等待,实际上您的过滤器将始终返回一个承诺,并且承诺始终为真..
await Promise.all
将等待从Promise.all
返回的承诺。如果listStudent
本身就是一个promise,那么你尝试使用promise 就好像它已经解决了 并将它传递给Promise.all
。我建议查看 Promise 和异步代码。
@VLAZ 谢谢你的知识,是的,我想我应该这样做。
【参考方案1】:
过滤/映射等,不支持async
的使用方式。
例如。 filter 期望一个真或假,你返回的承诺async
函数始终是一个承诺。
await Promise.all(
listStudent.filter(async (f) => <<<<---- This makes filter always return true
const count = await getCountTask(f.id);
查看您的代码,一个简单的解决方案就是删除过滤器,然后使用 map..
例如..
await Promise.all(
listStudent.map(async (f) =>
const count = await getCountTask(f.id);
if (count <= 3) return; //don't want this one.
let obj = ;
obj.id = f.id;
obj.age = f.age;
obj.status = 'Great';
totalStudent.push(obj);
)
)
由于Promise.all
返回一个数组,你也可以避免在totalStudent
上使用push
,。
例如。
totalStudent = await Promise.all(
listStudent.map(async (f) =>
const count = await getCountTask(f.id);
if (count <= 3) return; //don't want this one.
let obj = ;
obj.id = f.id;
obj.age = f.age;
obj.status = 'Great';
return obj;
)
)
上面的好处是还维护了退货单。
【讨论】:
另外更好的是进行映射操作,而不是滥用.map
进行简单的迭代。 return obj
最后而不是推送。如果您只是进行迭代,那么forEach
或使用循环。
是的,上面的代码确实有效。谢谢,所以我知道我上面的编码方式不起作用。谢谢你:D
@VLAZ 在这种情况下它实际上很方便,因为 promise 被推送到 Promise.all
,但是是的,return obj
会很好,只需将 Promise.all
的结果分配给 totalStudent。
@VLAZ 已更新,因此 map
正在做一些更有意义的事情,而不是将承诺传递给 Promise.all
我不会称它为“方便” - 它仍然是一种误用。 arr = await Promise.all(listStudends.map(getCountTask)); arr.filter().map()
没有误导。话虽如此,listStudends
应该是一个 Promise,而不是一个数组,所以我仍然对实际发生的事情感到困惑。以上是关于使用异步过滤和映射 Promise的主要内容,如果未能解决你的问题,请参考以下文章