Q1:async/await和同步调用的区别?
比如我在一段代码中使用了await fs.readFileWithPromise()
,这和直接使用fs.readFileSync()
在效果上有什么区别?
Q2:redis的pub/sub机制和node创建的web服务器监听端口从而触发事件有什么区别?
//redis的例子
redis.subscribe('sleep');
redis.on('message', async (channel, msg) => {
console.log(msg);
await sleep(3000);
console.log('end');
});
const sleep = ms => {
return new Promise(resolve => {
setTimeout(resolve, ms);
});
};
上面这个例子,我在另一个地方向sleep这个频道多次pub消息的时候,并不会阻塞,都能即时地打印出msg; 但是下面这个http服务器表现不同:
const http = require('http');
http.createServer(async (req, res) => {
if (req.url === '/favicon.ico') return;
if (req.url === '/') {
console.log('index');
await sleep(3000);
res.end('index');
}
if (req.url === '/test') {
console.log('test');
await sleep(3000);
res.end('test');
}
}).listen(3333);
当我请求’/‘时,在我没有得到响应之前,其他对’/‘的请求都会被挂起(服务端不打印’index’),但此时对’/test’的请求却能进入(打印’test’),为什么?如果线程被阻塞,那么应该都被挂起;如果没被阻塞,那么其他对’/'的请求为什么会被挂起?
最好能详细说一下它们在node中的执行流程(Event Loop层面)。 先在此谢过~~
a1,readFileSync 会阻塞进程, await的话,只会阻塞 async 当前块的代码,外面的代码该异步还是异步。
@chenzeZzz 和我的想法是一样的,不过如果是这样 为什么第二个问题里http服务器会有那样的现象?我觉得如果同时并发请求可能都会有响应 就是你说的外异;但是我在主线程已经进入async函数处理(处于内同状态),到sleep定时器超时之前,再发出请求,照理说都会被阻塞呀,为什么对于不同的请求会有不同的现象呢?
来自酷炫的 CNodeMD
针对Q2 我认为不应该会出现这种情况,await是不会阻塞线程的,多个对’/'的请求服务端会立即打印index,至于你上述代码出现这种情况怀疑与http.createServer有关系,它支持async函数吗,或者不太兼容。建议用koa框架测试下。
来自酷炫的 CNodeMD
@ProfutW node8.0 之后版本就自动支持 async 语法了
Q2 用你的demo测试了一下,是能够正常处理的,和你描述的问题不一致。 node -v v9.2.0
@dkvirus 对呀 所以这个现象我很疑惑
@chenzeZzz 换成while我知道肯定是阻塞的 我的意思是await应该不会阻塞线程 但是我上面的例子呈现的是阻塞了
@miserylee 我刚才又试了一遍 我的描述应该没问题的 你可以把sleep时间换长一点 比如10S 然后你对’/'发出两次请求 你会发现第一次请求等待10秒 页面有响应之后,第二次请求才会进入被处理(打印index) 我的node是8.9.4的 这两个版本应该不会在这个问题上有区别吧
@ProfutW 刚才用KOA也试了下,两次访问的确是串行的,第二个客户等到第一个客户响应了之后才开始打印index,好奇怪.
const koa = require('koa');
const sleep = ms => {
return new Promise(resolve => {
setTimeout(resolve, ms);
});
};
let app = new koa();
let num = 0;
app.use(async (ctx, next) => {
num++;
console.log('index',num);
await sleep(10000);
ctx.body = 'Hello World'+num;;
}).listen(3334);
@lovegnep 对呀 更奇怪的是 对其他url的访问却能够及时处理。。。
后台的console 显示每个请求都有 index/test, 没有被阻塞的
@lovegnep 我这里是正常的,两次请求都立刻打印index,node10.0.0,koa2.5.1
又试了几次,有时候会出现串行的情况,我再找找原因
啊
@chenzeZzz 对不同url访问是不会阻塞 但是对同一个就会
同一个页面刷新都会立刻打印index,两个页面同时请求只会打印第一个页面的index,此时刷新第一个页面就会立刻打印下一个index
奇怪的是3个页面请求时,断开第一个页面,剩下两个又会同时处理了。。。(难道是因为剩下两个在同一次事件循环内,所以可以被同时处理?
不是koa或async的问题,http就是这样的
const http = require('http');
let num = 0;
http.createServer(()=>console.log(num++)).listen(3333);
@dislido 的确是这样。。。我试了在定时器后面输出内容 结果是不停刷新后 10S后全部一起输出 这样的话await是没有阻塞线程 可是是什么阻塞了服务器响应呢 难道从tcp连接开始一直到超时这段时间 http服务器都不能响应其他请求? 但是为什么对另一个路径的请求却可以被处理呢?
mark
我也发现了这个问题了,还以为是我哪里用的不对。 看到大家的讨论,自己试了一下,确实是浏览器的优化啊,终于解决了我的困惑。 对于同一个地址的请求,如果前一个请求没返回,第二个也不会发起。