Javascript 为什么在reduce期间没有为推送到原始数组中的项调用Array.reduce函数?
给定以下代码:Javascript 为什么在reduce期间没有为推送到原始数组中的项调用Array.reduce函数?,javascript,arrays,reduce,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
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);
}
});
const-ports=[null,3001];
函数getPort(端口)
{返回新承诺((解决、拒绝)=>
{//setTimeout模拟从操作系统获取端口
设置超时(()=>
{if(端口<3010)
{return reject();
}
返回resolve();
}, 2000);
});
}
端口.reduce(异步(acc、端口、索引)=>
{如果(!端口)
{返回;
}
尝试
{
const avail=等待获取端口(端口);
返回端口;
}
捕获(有效)
{ports.push(++端口);
}
});
为什么只为元素null
和3001
调用reduce函数,而不调用3002
,即使在reduce
调用结束时,数组端口
等于[null,3001,3002]
在最后一个reduce调用完成之前,原始数组已经有了一个新元素,那么为什么不为该元素调用它呢
代码的目的是尝试从给定的数量和增量开始查找可用端口,直到找到一个,或者达到上限
还有其他方法可以做到这一点,但是reduce
方法似乎是最简洁的,直到我遇到了这个死胡同 因为:
在第一次调用callbackfn
之前设置reduce
处理的元素范围。callbackfn
在调用reduce开始后附加到数组的元素将不会被callbackfn
访问。如果数组的现有元素发生更改,则传递到callbackfn
的值将是reduce
访问它们时的值;在调用reduce
开始之后和被访问之前删除的元素不会被访问
(我的重点)
但另外,由于回调是一个async
函数,在推送数组之前使用getPort
上的wait
,因此reduce
调用在对push
进行任何调用之前完成reduce
同步执行其工作,即使您将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}`);
}
异步函数findPort(开始,最大值){
用于(让端口=开始;端口<最大值;++端口){
试一试{
等待getPort(端口);
返回端口;
}捕获(e){
//继续找
}
}
抛出新错误(`没有找到从${start}开始并在${max}之前停止的可用端口');
}
实例:
函数getPort(端口){
返回新承诺((解析,拒绝)=>{//setTimeout以模拟从操作系统获取端口
设置超时(()=>{
如果(端口<3010){
返回拒绝();
}
返回resolve();
}, 200);
});
}
异步函数findPort(开始,最大值){
用于(让端口=开始;端口<最大值;++端口){
试一试{
等待getPort(端口);
返回端口;
}捕获(e){
//继续找
}
}
抛出新错误(`没有找到从${start}开始并在${max}之前停止的可用端口');
}
(异步()=>{
试一试{
log(“尝试3001到3020”);
let port=wait findPort(30013020);
log(`Got port${port}`);
}捕获(e){
错误(`Failed:${e}`);
}
试一试{
log(“尝试3001到3009”);
let port=wait findPort(3001309);
log(`Got port${port}`);
}捕获(e){
错误(`Failed:${e}`);
}
})();代码>因为:
在第一次调用callbackfn
之前设置reduce
处理的元素范围。callbackfn
在调用reduce开始后附加到数组的元素将不会被callbackfn
访问。如果数组的现有元素发生更改,则传递到callbackfn
的值将是reduce
访问它们时的值;在调用reduce
开始之后和被访问之前删除的元素不会被访问
(我的重点)
但另外,由于回调是一个async
函数,在推送数组之前使用getPort
上的wait
,因此reduce
调用在对push
进行任何调用之前完成reduce
同步执行其工作,即使您将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}`);
}
异步函数findPort(开始,最大值){
用于(让端口=开始;端口<最大值;++端口){
试一试{
等待getPort(端口);
返回端口;
}捕获(e){
//继续找
}
}
抛出新错误(`没有找到从${start}开始并在${max}之前停止的可用端口');
}
实例:
函数getPort(端口){
返回新承诺((解析,拒绝)=>{//setTimeout以模拟从操作系统获取端口
设置超时(()=>{
如果(端口<3010){
返回拒绝();
}
返回resolve();
}, 200);
});
}
异步函数findPort(开始,最大值){
用于(让端口=开始;端口<最大值;++端口){
试一试{
等待getPort(端口);
返回端口;
}捕获(e){
//继续找
}