给出以下代码:
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);
}
});
为什么只在元素null
和3001
而不是3002
上调用reduce函数,即使在reduce
的末尾调用数组ports
等于[null, 3001, 3002]
?
在最后一次reduce调用完成之前,原始数组已经具有一个新元素,为什么还不为该元素调用它?
该代码的目的是尝试找到一个以给定数字开始并递增的可用端口,直到找到一个或达到上限为止。
还有其他方法可以执行此操作,但是reduce
方法似乎是最简洁的方法,直到我陷入僵局为止。
答案 0 :(得分:3)
由
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}`);
}
数组的用途,所以...