在Node.js中,Promise是同步还是异步的?

22

我在 Promise 中感到很困惑。它是同步还是异步的?

return new Promise (function(resolved,reject){
    //sync or async? 
});

1
Asynchronous - Alexander Nied
7个回答

42

传递给 Promise 构造函数的函数会同步执行,但依赖其解决的任何内容都会异步调用。即使Promise立即解决,任何处理程序也会异步执行(类似于使用 setTimeout(fn, 0))-主线程首先运行到结束。

无论您在哪个JavaScript环境中 - 无论您是在Node还是浏览器中,这都是正确的。

console.log('start');
const myProm = new Promise(function(resolve, reject) {
  console.log('running');
  resolve();
});
myProm.then(() => console.log('resolved'));
console.log('end of main block');


但根据 Mozilla 网站的说法,你传递的函数是异步的。请参阅以“通常情况下,它的工作方式如下:tetherFunction 中的操作...”开头的段落。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise - Aung Khant
1
这是指将回调 API 转换为 Promise 的通常方式,具体方法请参见 此处。在这种情况下,在 tetherFunction 中调用一个异步的、基于回调的函数,当该回调运行时,调用 resolve - CertainPerformance
不错!你可能想把这个放在你的答案里,因为这让很多人感到困惑。 - Aung Khant
更准确地说,您传递到Promise构造函数中的函数会立即(同步)运行,但函数内部的代码是异步运行的。 - CodeJonSnow

6
承诺本身不完全是同步或异步的。当您创建一个承诺时,您传递给它的回调立即执行,并且在该函数产生之前,没有其他代码可以运行。请考虑以下示例:

new Promise(function(resolve, reject) {
  console.log('foo');
})
console.log('bar');

承诺内部的代码(同步代码)必须完成后,承诺外部的代码才能开始执行。

话虽如此,承诺是处理异步代码的常见方法。承诺最常见的用例是表示以异步方式生成或获取的某些值。依赖于该值的逻辑可以通过使用 .then() 或相关的 Promise 方法来异步等待该值可用的回调函数。


1
同步意味着代码只能在前一个任务/代码行完成后才能运行。 异步意味着两个代码片段可以并行运行。 除非您使用等待语法等待它完成,否则承诺内部的代码不需要等待承诺外部的代码完成,这会将异步转换为同步。 - Leo Lei
1
正如您从示例中所看到的那样,承诺之外的代码实际上会等待承诺内部的代码产生结果后再执行。承诺本身并不是异步的,它们只是表示可能由异步过程生成的值的一种方式。 - Ryan Jenkins
好的,说得对。但我仍然觉得这个语句有点难以理解:“依赖于该值的逻辑可以异步等待”。我认为该值是同步等待的 - 这正是同步的含义,代码在某些其他代码完成之前无法执行。 - Leo Lei

5
这段代码可以更加清晰明了:
        console.log("0");
        new Promise((resolve, reject) => {
          console.log("1");
          resolve();
        }).then(() => {
          console.log("2");
        });
        console.log("3");

代码输出:0 1 3 2。 因此,当主回调函数同步运行时,then以异步方式运行。

1
简单明了 - kittu

2

我认为其他答案不准确。

new Promise (executor_function)

在这里,executor_function将作为Promise初始化的一部分立即运行 --- 这意味着Promise init将同步执行,但并不意味着executor_function内部的代码必须同步运行,相反,executor_function内部的代码也可以异步运行,例如:

new Promise ((resolve, reject) => {
    setTimeout(resolve, 1000); // wait 1s 
})

2
当您创建一个Promise并传递一个回调函数时,该回调函数会立即执行(同步)。

const promise= new Promise(function(resolve, reject) {
      //doing some logic it gonna be executed synchronously
       console.log("result");
    })
    console.log("global log")
    

但是当你使用.then()方法来解决它时,它将以异步方式执行。例如:

const promise = new Promise(function(resolve, reject) {
  //doing some logic it gonna be executed synchronously

  resolve("fullfiled")
})
promise.then(v => {
  console.log(v)
})
console.log("global log")


1
承诺在 Javascript 中就像普通类一样。假设您正在创建自己的 Promise 实现,您的 promise 类大致如下所示。请注意,在构造函数中,您期望传递一个方法,立即调用该方法并将 resolve 和 reject 作为参数传递。
class Promise {
    constructor(method) {
        method(resolve, reject)
    }

    resolve() { ... }

    reject() { ... }

    then() { ... }
}

当你使用 new Promise() 时,你只是创建一个新的对象。你的 Promise 构造函数 将运行,并立即调用该方法。因此,你的 promise 中的代码会同步执行。
return new Promise (function(resolved,reject){
    //sync or async? 
});

如果在你的函数内部调用了另一个异步函数,那么这个函数会异步执行,否则,其他所有内容都会同步执行。
如果你使用then链接promise,那么只有在第一个promise调用resolve()后才会调用它。
return new Promise (function(resolve,reject){
  const a = 5*5; // sync operation.
  db.save(a, function callback() { // async operation.
    resolve() // tells promise to execute `then` block.
  });
});

0

const promise = new Promise(function(resolve, reject) {
  //doing some logic it gonna be executed synchronously
 console.log("check")
  resolve("fullfiled")
})
promise.then(v => {
  console.log(v)
})
console.log("global log")


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接