javascript - 在不同时间分配给数组会产生不同的结果

标签 javascript arrays ecmascript-2017

我有这两个不同的代码,它们略有不同,但产生不同的结果:

(async () => {
  const results = new Array(concurrentBrowsers).fill({});
  const browsers = [];
  for (let index = 0; index < concurrentBrowsers; index++) {
    browsers.push(
      (async function() {
        let i = index;
        const browser = await puppeteer.launch({ headless });
        const page = await getNewPage({ browser });
        results[i].loginPage = await timer(actions.loginPage, { page }); // <---- this line
        results[i].homePage = await timer(actions.homePage, {
          page,
          username,
          password
        });
        console.log(i, results[i]);
        browser.close();
      })()
    );
  }
  await Promise.all(browsers);
})();

结果

1 { loginPage: 2.924, homePage: 19.939 }
2 { loginPage: 2.924, homePage: 21.388 }
3 { loginPage: 2.924, homePage: 21.122 }
0 { loginPage: 2.924, homePage: 21.305 }
4 { loginPage: 2.924, homePage: 21.6 }

还有一个:

(async () => {
  const results = new Array(concurrentBrowsers).fill({});
  const browsers = [];
  for (let index = 0; index < concurrentBrowsers; index++) {
    browsers.push(
      (async function() {
        let i = index;
        const browser = await puppeteer.launch({ headless });
        const page = await getNewPage({ browser });
        let loginPageTime = await timer(actions.loginPage, { page }); // <---- this line
        let homePageTime = await timer(actions.homePage, {
          page,
          username,
          password
        });
        results[i].loginPage = loginPageTime;
        results[i].homePage = homePageTime;
        console.log(i, results[i]);
        browser.close();
      })()
    );
  }
  await Promise.all(browsers);
})();

结果

2 { loginPage: 3.291, homePage: 17.911 }
4 { loginPage: 3.226, homePage: 18.949 }
1 { loginPage: 3.047, homePage: 22.619 }
0 { loginPage: 3.291, homePage: 24.508 }
3 { loginPage: 3.059, homePage: 26.391 }

第一个代码有一个错误,似乎 loginPage 结果始终取自最后一次迭代,并且如您所见,在所有迭代中设置为相同的值。

唯一的区别是我将第一个示例中的计时器结果分配给 results[i].loginPage,而在第二个示例中将计时器的结果分配给 loginPageTime

有人可以解释一下这种差异吗?

谢谢

最佳答案

事实上,两个代码变体都有相同的问题,但第二个代码块没有显示出了什么问题:

const results = new Array(concurrentBrowsers).fill({});

这将创建一个(!)空对象并将其分配给所有数组条目。您对该对象所做的任何更改都将通过所有数组条目看到,因为它们都引用同一个对象。

您在第一个版本中看到不一致的原因是,同一迭代中的两个 await 表达式之间发生了其他赋值,而第二个代码版本则不会分配直到 console.log 之前。

您可以按如下方式对结果执行正确的初始化:

const results = Array.from(new Array(concurrentBrowsers), _ => ({}));

关于javascript - 在不同时间分配给数组会产生不同的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45798929/

相关文章:

javascript - 如何在 OpenLayers 2 中启用街景控件?

javascript - 来自不同数组的不同值并在表中并排附加在一起

python - 如何获得 numpy 掩码数组中的掩码行数?

javascript - 等待回调函数

javascript - axios获取URL参数字符串不接受

javascript - ES2017 Async/await 函数 - 它们只适用于 promises 吗?

javascript - 如何在 findAll 上的 node.js Sequelize 中具有多个关联/条件/包含

javascript - Laravel - 在使用 jQuery AJAX 提交表单之前检查用户名是否已存在

php - 获取分组在数组中的数据库值

javascript - 按元素 Id 切换日历组件中的类突出显示每个月的相同日期