给出以下代码:
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);
}
});
为什么即使在 reduce 结束时,也仅对元素
调用数组null
和 3001
而不是 3002
调用归约函数ports
等于[null, 3001, 3002]
?
在最后一次reduce调用完成之前,原始数组已经有了一个新元素,那么为什么没有为该元素调用它呢?
代码的目的是尝试找到一个可用的端口,从给定的数字开始并递增,直到找到一个,或者达到上限。
还有其他方法可以做到这一点,但是 reduce
方法似乎是最简洁的,直到我遇到这个死胡同。
最佳答案
The range of elements processed by
reduce
is set before the first call tocallbackfn
. Elements that are appended to the array after the call to reduce begins will not be visited bycallbackfn
. If existing elements of the array are changed, their value as passed tocallbackfn
will be the value at the timereduce
visits them; elements that are deleted after the call toreduce
begins and before being visited are not visited.
(我的重点)
但单独而言,由于您的回调是一个 async
函数,因此在推送数组之前在 getPort
上使用 await
,因此 reduce
调用在任何 push
调用发生之前完成。 reduce
会同步完成工作,即使您给它一个async
函数也是如此。 async
函数返回promises(如果你仔细观察,第二个回调上的acc
将是一个promise)。
The aim of the code is to try and find an available port starting at a given number and increment until we find one, or we hit an upper limit.
一个简单的循环会......更简单:
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}`);
}
实例:
function getPort(port) {
return new Promise((resolve, reject) => { // setTimeout to simulate getting port from OS
setTimeout(() => {
if (port < 3010) {
return reject();
}
return resolve();
}, 200);
});
}
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}`);
}
(async () => {
try {
console.log("Trying 3001 through 3020");
let port = await findPort(3001, 3020);
console.log(`Got port ${port}`);
} catch (e) {
console.error(`Failed: ${e}`);
}
try {
console.log("Trying 3001 through 3009");
let port = await findPort(3001, 3009);
console.log(`Got port ${port}`);
} catch (e) {
console.error(`Failed: ${e}`);
}
})();
...但我不太明白 ports
数组的用途,所以...
关于javascript - 为什么在reduce过程中插入原始数组的项目没有调用Array.reduce函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53223948/