Array.prototype.map() 之后的下一个函数是不是可以安全地假设 map 中的所有回调都已返回?

Posted

技术标签:

【中文标题】Array.prototype.map() 之后的下一个函数是不是可以安全地假设 map 中的所有回调都已返回?【英文标题】:Can the next function after Array.prototype.map() safely assume all callback in map have returned?Array.prototype.map() 之后的下一个函数是否可以安全地假设 map 中的所有回调都已返回? 【发布时间】:2019-03-18 13:02:30 【问题描述】:

我知道Array.prototype.map 是一个同步操作。另一方面如果map函数是一个回调函数(异步)undefined会立即返回。

所以我的问题是下一个函数是否可以安全地假设所有回调函数都已完成? 一个示例代码可能会让我的问题更清楚:

results = files.map(file => 
  fs.readFile(file, (err, data) => 
    if (err) throw err;
    return process(file) //will return the processed value, NOT a promise
  );
)
//I know results will be [undefined, undefined, undefined ...]
//But can I assume all the files have been processed if I reach here?
console.log('done')

我不关心返回值。这就是为什么我不想打扰await/async。我只想确保所有回调函数都已调用并返回。这可能吗?

-------更新--------

除了答案之外,我发现这些文章还可以帮助我理解问题: https://medium.com/@antonioval/making-array-iteration-easy-when-using-async-await-6315c3225838Using async/await with a forEach loop

我必须使用 promise 来确保所有回调迭代都已完成。所以使用bluebird promise.map 有助于减少样板代码

【问题讨论】:

您实际上 return 箭头函数中没有任何内容,因此它是未定义的,如果您返回承诺,您可以在返回的数组上使用 Promise.all 我不想使用 await b/c 我不在乎映射数组我只想知道是否返回所有回调函数。什么是“正确”的做法? @JonasWilms 我的示例代码错误(我已更正)我确实返回了箭头函数,但我相信我仍然会得到一个包含所有未定义项的数组。我认为我的问题与您在其他两个问题中提到的不同。 同意,这不是一个真正的骗局,道歉 @Qiulang no, map 不保证任何回调已经被调用,事实上,它甚至不知道你传递给@987654331的异步回调@。它只关心map 回调本身的返回值,即undefined。去使用 promise,你仍然可以忽略它们的结果——但你需要它们能够等待它们。 【参考方案1】:

你必须让回调函数有前途,然后你可以使用 Promise.all:

 const results = Promise.all(files.map(file => new Promise(resolve => 
  fs.readFile(file, (err, data) => 
    if (err) throw err;
    resolve(process(file));
  );
 ));

 results.then(() => 
   console.log('done')
   //...
 );

【讨论】:

这是我一开始就试图避免的。我知道我可以使用 promise.all/await 但我不想!因为我只需要确保 map 之后的下一个函数可以安全地假设所有回调都已完成,因此问题就来了。 @qiulang 这是唯一的方法。或者你使用fs.readFileSync,但这会很慢 但我做了一些测试,例如在每个回调中返回之前打印处理后的值,并发现这些打印始终在我的下一个函数之前运行。我知道我不应该指望这一点,但另一方面 b/c 地图是同步的,我仍然想知道这是否可能 @quilang 正如我所说,如果您希望它同步运行,请使用fs.readFileSync

以上是关于Array.prototype.map() 之后的下一个函数是不是可以安全地假设 map 中的所有回调都已返回?的主要内容,如果未能解决你的问题,请参考以下文章

TypeScript Array.prototype.map 声明

实现对象的 Map 函数类似 Array.prototype.map

...var 在 Array​.prototype​.map() 上的含义是啥 [重复]

Array.prototype.map()

以函数式协变方式使用 Array.prototype.map

使用 Array.prototype.map 将具有索引的对象插入二维数组