Javascript 一个同步进程和一个异步进程的组合是否同时运行?
请您告诉我,这段代码末尾列出的结果是否意味着承诺Javascript 一个同步进程和一个异步进程的组合是否同时运行?,javascript,concurrency,promise,Javascript,Concurrency,Promise,请您告诉我,这段代码末尾列出的结果是否意味着承诺p5()和f5()正在同时处理 在我的项目代码中,sync()生成并返回一个文档片段来替换DOM中的节点,但不替换它,p5()是一个indexedDB数据库读写操作。除非数据库操作成功,否则我不想用新片段替换现有节点,我想根据p5()或f5()可能失败的原因提供用户选项 我想知道是否将同步函数sync()放在承诺中,这样它就可以放在promise.allselled中,从而允许这两个进程同时运行,然后在两者都解决后检查错误,而不是等待p5()在sy
p5()
和f5()
正在同时处理
在我的项目代码中,sync()
生成并返回一个文档片段来替换DOM中的节点,但不替换它,p5()
是一个indexedDB数据库读写操作。除非数据库操作成功,否则我不想用新片段替换现有节点,我想根据p5()
或f5()
可能失败的原因提供用户选项
我想知道是否将同步函数sync()
放在承诺中,这样它就可以放在promise.allselled
中,从而允许这两个进程同时运行,然后在两者都解决后检查错误,而不是等待p5()
在sync()
中开始构建片段之前完成
我对并发性知之甚少,但这些结果似乎表明,sync()
或f5()
花了两秒钟完成,在p5()
之前花了三秒钟完成,所有问题都在五秒钟内解决,而不是总共花了七秒钟
多谢各位
函数p5(){
返回新承诺((解决、拒绝)=>{
setTimeout(()=>resolve('p5 resolved at:'+new Date()),5000);})
函数f5(){
返回新承诺((解决、拒绝)=>{
请尝试{解析(sync());}
捕获(e){拒绝(e)}
}); }
函数sync(){
让我,str='';
对于(i=0;i<50000000;i++)str=str+'一个文本字符串';
i=str=null;
返回“同步完成时间:”+新日期();
}
log('start:'+newdate());
Promise.allSettled([p5(),f5()]),然后((r)=>{console.log(r[0]);console.log(r[1]);});
/*结果:
开始时间:星期六2020年2月22日00:36:53 GMT-0500(东部标准时间)
r[0]:
{“状态”:“已完成”,
“值”:“p5解析时间:星期六2020年2月22日00:36:58 GMT-0500(东部标准时间)”}
r[1]:
{“状态”:“已完成”,
“值”:“同步完成时间:星期六2020年2月22日00:36:55 GMT-0500(东部标准时间)”}
*/
因为您首先调用了实际的异步操作p5()
,它将在同步操作f5()
运行时启动并在后台运行
异步p5()
在同步代码完成之前无法处理其完成,因为主JS线程一次只能做一件事,而同步代码正在阻塞事件循环,因此在同步f5()
完成之前,无法处理任何异步操作的完成事件
如果将代码切换为重新排序p5()
和f5()
,如下所示:
Promise.allSettled( [ f5(), p5() ] ).then(...)
然后,就不会有并发,因为在f5()
完成之前,p5()
甚至都不会启动
我想知道,如果将同步函数sync()
放在一个承诺中,这样就可以将它放在一个承诺中。allSettled将允许这两个进程同时运行,然后在两者都解决后检查错误,而不是等到p5()完成后才开始在sync()
中构建片段
仅供参考,将对
sync()
的调用包装在承诺中并没有真正的好处。你也可以这样做:
p5().then(...);
f5();
这将使您获得相同的总体执行时间,直到两者都完成,因为p5()
仍然首先启动并在后台运行,并且在阻塞f5()
完成之前无法处理其完成事件
另外,您应该知道,您不必在承诺中包装
sync()
。您可以将普通值传递给Promise.all()
或Promise.allsolited()
。所以,你也可以这样做:
Promise.allSettled([p5(), sync()]).then(...)
而且,它也会起同样的作用。谢谢您的解释。我可以再问一个问题吗?如果您不将
sync()
包装在承诺中,并且希望捕获函数中多个代码部分中的潜在错误以指示错误的位置,那么除了从catch
中使用return
之外,还有其他方法返回自定义错误消息吗。我之所以这样问,是因为即使返回错误,状态
似乎也将始终得到满足。谢谢。@Gary-如果sync
可以同步抛出,那么将其封装在承诺中可能会有所帮助,这样您就可以更容易地将其完成捕获为一个被拒绝的承诺,并完成p5()
。如果您想捕获sync()
中的异常并将其转换为返回的错误(而不是异常),那么您只需返回一些可检测的错误值(通常是错误
对象或错误
对象的子类),这是正确的。