为什么在reduce期间不调用Array.reduce函数来将项目推入原始Array中?

时间:2018-11-09 10:27:01

标签: javascript arrays reduce

给出以下代码:

const ports = [null,3001];

function getPort(port)
{ return new Promise((resolve, reject) =>
  { // setTimeout to simulate getting port from OS
    setTimeout(() =>
    { if(port < 3010)
      { return reject();
      }
      return resolve();
    }, 2000);
  });
}

ports.reduce(async (acc, port, index) =>
{ if(!port)
  { return;
  }

  try
  {
    const avail = await getPort(port);
    return port;
  }
  catch(avail)
  { ports.push(++port);
  }
});

为什么只在元素null3001而不是3002上调用reduce函数,即使在reduce的末尾调用数组ports等于[null, 3001, 3002]

在最后一次reduce调用完成之前,原始数组已经具有一个新元素,为什么还不为该元素调用它?

该代码的目的是尝试找到一个以给定数字开始并递增的可用端口,直到找到一个或达到上限为止。

还有其他方法可以执行此操作,但是reduce方法似乎是最简洁的方法,直到我陷入僵局为止。

1 个答案:

答案 0 :(得分:3)

因为that's how it's defined

  

reduce处理的元素范围是在第一次调用callbackfn之前设置的。 callbackfn将不会访问在调用reduce开始后附加到数组的元素。如果更改了数组的现有元素,则传递给callbackfn的元素的值将是reduce访问他们时的价值;在访问reduce之后并且被访问之前删除的元素不会被访问。

(我的重点)

但是要分开使用,因为您的回调是在推送数组之前在async上使用await的{​​{1}}函数,所以getPort调用在对{{1}的任何调用之前完成甚至发生。 reduce同步完成其工作,即使您将其交给push函数也是如此。 reduce函数返回 promises (如果您看,第二个回调中的async将是一个应许)。

  

该代码的目的是尝试找到一个以给定数字开始并递增的可用端口,直到找到一个或达到上限为止。

一个简单的循环会...更简单:

async

实时示例:

acc

...但是我无法完全了解async function findPort(start, max) { for (let port = start; port < max; ++port) { try { await getPort(port); return port; } catch (e) { // keep looking } } throw new Error(`No available port found starting at ${start} and stopping before ${max}`); } 数组的用途,所以...