理解承诺和未定义的变种的奇怪错误

问题描述 投票:0回答:1

我刚刚发现,当2个请求几乎在同一时间被触发时,我的API做了奇怪的事情。

我想明白了,问题是我在下面的 "用户 "变量前缺少了 "var "声明,但我真的很好奇导致下面描述的错误的根本问题。

我有两个API端点 调用同一个函数,如下所示。

router.get('/refresh_session_token', function (req, res) {

   let user_id = req.body.user_id // The value sent is 8

   findUserWithId(user_id)
    .then(user_data => {
      user = user_data // I forgot 'var' here
    })
    .then(() => {
      console.log(user) // This should always show user data from user_id = 8
    })
}


router.get('/resend_invite', function (req, res) {

   let user_id = req.body.user_id // The value sent is 18

   findUserWithId(user_id)
    .then(user_data => {
      user = user_data // I forgot 'var' here
    })
    .then(() => {
      console.log(user) // This should always show user data from user_id = 18
    })
}

const findUserWithId = (id) => {
  return knex.raw(`SELECT * FROM users WHERE id = ?`, [id]).then((data) => data.rows[0])
}

所有这些代码都在同一个文件里,我通过模块.exports = router导出。

我发现的是,如果我触发了端点 刷新会话标记resend_invite 在几乎相同的时间,每个用户都使用两个不同的user_id,但有时,我的console.log会返回相同的结果,就像我使用相同的user_id一样。

添加var到user后,问题就解决了,但我很惊讶后台到底发生了什么。

你有什么想法吗?

javascript node.js express promise router
1个回答
2
投票

当你没有声明你的变量,而且你没有在Javascript的模块中运行你的 strict 模式,然后对该变量进行第一次赋值。

user = user_data

创建一个自动的全局变量,名为 user. 这意味着你的两条路由共享同一个变量。

而且,由于你的两个路由都有异步操作,即使在单线程的情况下,你的两个路由仍然可以同时在飞行中,并且都试图使用同一个全局变量。 一个路由会覆盖另一个路由的值。 这在基于服务器的代码中是一场灾难,因为通常情况下,这个bug不会显示出来,直到你进入生产阶段,而且真的很难找到一个可重现的案例。

这里最好的答案是始终在严格模式下运行你的代码,然后JS解释器会将此作为一个错误,你将永远不会被允许首先以这种方式运行你的代码。 这个错误会很快很容易被发现。

然后很明显,总是用 letconst. 有非常,非常少的理由去使用。var 不啻 letconst 让你对变量的范围有更多的控制。

要在严格模式下运行你的模块,请在任何其他Javascript语句之前插入this:

'use strict';

在任何其他Javascript语句之前插入这个.

或者,使用一些类似TypeScript的东西,它不会让你做一些不声明变量的草率事情。

© www.soinside.com 2019 - 2024. All rights reserved.