JavaScript Promise是异步的吗?

Jan*_*yne 8 javascript asynchronous promise

只是一个澄清的简单问题:JavaScript Promise异步吗?我一直在阅读很多帖子Promise和异步编程(即ajax请求).如果Promise不是异步,我们如何做到这一点?

例如,我有一个函数来包装的功能f与参数数组args内的Promise.没有什么f本质上是异步的.

function getPromise(f, args) {
 return new Promise(function(resolve, reject) {
  var result = f.apply(undefined, args);
  resolve(result);
 });
}
Run Code Online (Sandbox Code Playgroud)

为了使这个异步,我阅读了一些SO帖子,并决定setTimeout很多人建议使代码无阻塞.

function getPromise(f, args) {
 return new Promise(function(resolve, reject) {
  setTimeout(function() { 
   var r = f.apply(undefined, args);
   resolve(r);
  }, 0);
 });
}
Run Code Online (Sandbox Code Playgroud)

这种方法是否setTimeout可以使代码在内部无阻塞Promise

(请注意,我不依赖于任何第三方Promise API,只是浏览器支持的内容).

Pau*_*aul 20

我认为你是在误解工作.JavaScript代码总是*阻塞 ; 那是因为它在一个线程上运行.Javascript中异步编码风格的优点是像I/O这样的外部操作不需要阻塞该线程.处理来自I/O的响应的回调仍然是阻塞的,并且没有其他JavaScript可以同时运行.

*除非您考虑运行多个进程(或浏览器上下文中的WebWorkers).

现在针对您的具体问题:

只是一个澄清的简单问题:JavaScript Promise是异步的吗?

不,传递给Promise构造函数的回调是立即和同步执行的,尽管它可以启动异步任务,例如超时或写入文件,并等到异步任务完成后再解析promise; 事实上,这是承诺的主要用例.

这种使用setTimeout的方法是否可以在Promise中使代码无阻塞?

不,它所做的只是改变执行的顺序.您的脚本的其余部分将执行直到完成,然后当没有其他任何操作时,将执行setTimeout的回调.

为了澄清:

console.log( 'a' );

new Promise( function ( ) {
    console.log( 'b' );
    setTimeout( function ( ) {
        console.log( 'D' );
    }, 0 );
} );

// Other synchronous stuff, that possibly takes a very long time to process

console.log( 'c' );
Run Code Online (Sandbox Code Playgroud)

上述程序确定性地打印:

a
b
c
D
Run Code Online (Sandbox Code Playgroud)

这是因为在主线程没有任何事情要做之后(在记录'c'之后),setTimeout的回调将不会执行.

  • 我知道这个答案是前一段时间写的,但我很好奇是否有人对此有任何参考?根据MDN的说法,承诺是异步的:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise。 (2认同)
  • 我也想弄清楚 Promise 是异步的还是同步的。查看 - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises '本质上,承诺是一个返回的对象,您可以将回调附加到该对象,而不是将回调传递到函数中。' 我知道 Promise 本身是同步的,但是,它最常与异步函数结合使用。因此,有人说“Promise 是一个代表异步操作最终完成或失败的对象”,其中的示例包括异步函数和普通函数。 (2认同)
  • @ChrisPaton我认为MDN在描述Promises的行为方面很草率:“请注意,promise保证是异步的。”它应该说的是“请注意,解决promise保证是异步的。” 就像在答案中一样,[构造函数的“执行器”](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/Promise#syntax) 被同步调用。 (2认同)