【问题标题】:Passing a function to Promise.then results in a different behaviour than passing a nested function将函数传递给 Promise.then 会导致与传递嵌套函数不同的行为
【发布时间】:2020-07-26 11:29:17
【问题描述】:

以下代码

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 函数需要接受一个函数(在本例中为箭头),然后我可以从该函数内部进行进一步的函数调用。

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

【问题讨论】:

    标签: javascript asynchronous promise es6-promise


    【解决方案1】:

    .then() 需要一个回调函数,该函数将在调用 .then() 方法的 Promise 时调用 - 实现。

    当你这样做时

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

    doSomething() 不是注册一个稍后会调用的回调函数,而是立即调用

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

    .then(doSomething)
    

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

    .then(doSomething("2nd Call")) 仅在doSomething 返回函数时才有效。在这种情况下,返回的函数将被注册为回调,并在 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);
      })

    【讨论】:

      【解决方案2】:

      如果你使用then(fn()),它不会返回值供下一个.then(...)使用,所以它可以立即继续。

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

      类似于功能之间的区别

      function a () {
         stuff
      }
      
      function b (){
        return stuff
      }
      

      【讨论】:

        猜你喜欢
        • 2017-06-24
        • 1970-01-01
        • 2020-07-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多