将函数传递给 Promise.then 会导致与传递嵌套函数不同的行为

Passing a function to Promise.then results in a different behaviour than passing a nested function

以下代码

function doSomething(msg){ 
    return new Promise((resolve, reject) => {
      setTimeout(
        () => {
          console.log(msg);
          resolve();
        }, 
        2000);
    }) 
}

let start = Date.now();  
let end;  
doSomething("1st Call")
  .then(()=>doSomething("2nd Call"))
  .then(()=>doSomething("3rd Call"))
  .then(()=>{
    end = Date.now();
    console.log('start',start);
    console.log('end',end);
    console.log('elapsed time',end-start);
  }) 

打印第一个调用、第二个和第三个调用,每个 console.log 语句之间间隔 2 秒,正如预期的那样

但是,如果我从 then 块中删除箭头函数,行为就完全不同了,即

doSomething("1st Call")
  .then(doSomething("2nd Call"))
  .then(doSomething("3rd Call"))
  .then(()=>{
    end = Date.now();
    console.log('start',start);
    console.log('end',end);
    console.log('elapsed time',end-start);
  }) 

使用此代码,所有 console.log 语句同时打印,经过的时间仅为 2 秒,而不是每个函数 2 秒(第一个示例中总共 6 秒)

换句话说,为了使代码正常工作,then 函数需要接受一个函数(在本例中为箭头函数),然后从该函数内部进行进一步的函数调用。

为什么我不能直接传递函数,为什么需要嵌套在另一个函数中?

.then() 需要一个回调函数,当调用 .then() 方法的 Promise 完成时调用该回调函数。

当你这样做时

.then(doSomething("2nd Call"))

没有注册稍后调用的回调函数,doSomething() 立即被调用

您可以将对函数的引用传递给 .then() 方法,.then() 将在 Promise 完成时调用该函数。

.then(doSomething)

但是您将无法将任何参数传递给 doSomething 函数。

.then(doSomething("2nd Call")) 仅在 doSomething returns 函数时有效。在这种情况下,返回的函数将被注册为回调,并在 Promise 满足时被调用。

您可以使用 .bind() 获取一个函数,该函数将用作 .then() 方法的回调

function doSomething(msg){ 
    return new Promise((resolve, reject) => {
      setTimeout(() => {
          console.log(msg);
          resolve();
        }, 2000);
    }); 
}

let start = Date.now();  
let end;  

doSomething("1st Call")
  .then(doSomething.bind(null, '2nd Call'))
  .then(doSomething.bind(null, '3rd Call'))
  .then(()=>{
    end = Date.now();
    console.log('start',start);
    console.log('end',end);
    console.log('elapsed time',end-start);
  })

如果您使用 then(fn()),它不会 return 为下一个 .then(...) 使用的值,因此它可以立即继续。

当您使用.then(variable => fn())时,下一个.then(...)将等待第一个解决或拒绝。

类似于函数之间的区别

function a () {
   stuff
}

function b (){
  return stuff
}