Можно ли одновременно запустить два куска кода в node.js? - PullRequest
2 голосов
/ 22 октября 2019

Как я понимаю, неблокирующая концепция это может произойти. Но архитектура одной угрозы node.js заставила меня усомниться в этом.

Допустим, у меня есть две конечные точки на моем HTTP-сервере:

app.get('/one', ()  => {
    global.counter = 'A'
    global.counter += 'A'
    global.counter += 'A'
    ...
})

app.get('/two', ()  => {
    global.counter = 'B'
    global.counter += 'B'
    global.counter += 'B'
    ...
})

Что произойдет, если сервер почти получит два запросав то же время. Может ли global.counter закончиться сочетанием A и B?

Как насчет использования async/await как global.counter += await getB()?

1 Ответ

1 голос
/ 22 октября 2019

В вашем примере global.counter никогда не может заканчиваться сочетанием 'A' и 'B', потому что каждый обратный вызов функции будет выполняться после того, как предыдущий уже завершился. Запросы будут обрабатываться асинхронно , но не параллельно , поскольку для пользовательского кода выполняется только один поток.

Однако, когда у вас есть асинхронные операции внутри функции обратного вызова, например, выборка по сети, доступ к базе данныхили чтение файла, второй пользовательский запрос может завершиться раньше первого и, таким образом, изменить глобальное состояние до того, как первая функция получит к нему доступ.

let state;

function timeout(ms) {
  return new Promise(resolve => {
    setTimeout(resolve, ms)
  })
}

async function req1() {
  state = 'A';
  await timeout(100);
  state += 'A';
  console.log(`Req 1: ${state}`);
}

async function req2() {
  state = 'B';
  await timeout(50);
  state += 'B';
  console.log(`Req 2: ${state}`);
}

req1();
req2();

// Prints:
// "Req 2: BB"
// "Req 1: BBA"

Это одна из причин, почему это плохая идеяполагаться на глобальное состояние в обратных вызовах запросов HTTP-сервера (например, Express или Koa).

...