javascript - 为什么在reduce过程中插入原始数组的项目没有调用Array.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 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 结束时,也仅对元素 null3001 而不是 3002 调用归约函数调用数组ports等于[null, 3001, 3002]

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

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

还有其他方法可以做到这一点,但是 reduce 方法似乎是最简洁的,直到我遇到这个死胡同。

最佳答案

因为that's how it's defined :

The range of elements processed by reduce is set before the first call to callbackfn. Elements that are appended to the array after the call to reduce begins will not be visited by callbackfn. If existing elements of the array are changed, their value as passed to callbackfn will be the value at the time reduce visits them; elements that are deleted after the call to reduce 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/

相关文章:

javascript - strip : throw errnoException(process. _errno, 'spawn' );

JavaScript 删除 IIFE 事件监听器

javascript - 下划线返回数组中对象的索引,其中单词存在于对象内的句子中

python - 计算将数组中的值向上或向下舍入以最小影响平均值的点的算法

java - 扩展 "Movies example"最佳答案

javascript - 使用reduce和map获取数组中对象的频率

javascript - 调用 reduce 对对象数组求和返回 NaN

javascript - 为选项添加一个值

c# - 找到两个成对给定元素之间的最大距离

javascript - 在不连接的情况下创建 websocket