【问题标题】:How to use Array.prototype.map() with then() for connection.end()如何使用 Array.prototype.map() 和 then() 进行 connection.end()
【发布时间】:2025-12-20 03:30:11
【问题描述】:

我有一个错误TypeError: cars.map(...).then is not a function。我想在更新颜色时终止连接。

cars.map(function (item, i) {
    if (item.color === 'red') {
        updateColor(item.id)
    }
}).then(() => connection.end())

【问题讨论】:

  • map 仅适用于数组。您是否将cars 初始化为数组?再次then 也不适用于map
  • 你将then()链接到map(),你可以将then()链接到一个返回promise的函数
  • 我不确定这两者是如何连接的。如果您已经有一个cars 数组,那么您不需要连接,因此您可以在.map 调用之前简单地终止,并且什么都不会改变。或者你可以调用cars.map(/* ... */); connection.end();,它保证在映射操作之后运行。

标签: javascript node.js promise es6-promise


【解决方案1】:

此答案仅适用于updateColor 是异步且确实返回Promise 对象的情况。

.map 返回一个数组,而不是 Promise。您可以做的是使用.map 构建一个Promise 数组,然后使用Promise.all 将它们全部解析,然后处理结果。

下面的代码会执行所有的updateColor,等到它们完成后再停止连接。

Promise.all(cars.map((item, i) => {
    if (item.color === 'red') {
      return updateColor(item.id);
    }

    return false;
  }))
  .then(() => connection.end())

使用async/await 代替Promises

  await Promise.all(cars.map((item) => {
        if (item.color === 'red') {
          return updateColor(item.id);
        }

        return false;
      }));

   connection.end();

使用reduce 代替map

await Promise.all(cars.reduce((tmp, x) => (x.color === 'red' ? [
  ...tmp,

  updateColor(x.id),
] : tmp), []));

connection.end();

【讨论】:

    【解决方案2】:

    这里有几个问题:

    1. 当您不使用它创建的数组时,没有理由使用map。要遍历数组,请使用forEachany of several other mechanisms

    2. map 是一个完全同步的函数。要在它之后做某事,只需……在它之后做。

    3. then 是一种承诺方法(嗯,thenable)。 map 返回一个数组,而不是一个承诺。

    所以:

    for (const item of cars) {
        if (item.color === 'red') {
            updateColor(item.id)
        }
    };
    connection.end();
    

    如果 updateColor 异步执行其工作并且返回一个承诺,那么请参阅Grégory NEUT's answer

    【讨论】: