node.js中的两段代码可以同时是运行吗?
Can two piece of code be run at the same time in node.js?
根据我对非阻塞概念的理解,这可能会发生。但是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
吗?
像global.counter += await getB()
一样使用async/await
怎么样?
在您的示例中,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)中依赖全局状态不是一个好主意的原因之一。
根据我对非阻塞概念的理解,这可能会发生。但是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
吗?
像global.counter += await getB()
一样使用async/await
怎么样?
在您的示例中,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)中依赖全局状态不是一个好主意的原因之一。