【问题标题】:How the code after then runs if the Promise haven't been settled yet?如果 Promise 尚未解决,那么之后的代码如何运行?
【发布时间】:2021-04-15 06:42:53
【问题描述】:

当我们使用链链接一个 Promise 的,并且 Promise 由 then 返回,那么不属于 then 的代码如何> 链条在所有链条完成之前运行?代码如何跳过 then 调用?不应该在运行“console.log”代码行之前执行所有调用吗?

代码如下:

Promise.resolve('333')
    .then((res)=>{console.log(res);return new Promise((resolve,reject)=> {setTimeout(function(){console.log('Timeout');resolve(1);},10000);console.log('Something');})})
    .then((res)=>{console.log(res);return new Promise((resolve,reject)=> {console.log('Something');resolve(2);})})    
    .then((res)=>{console.log(res);return new Promise((resolve,reject)=> {console.log('Something');resolve(3);})})
    .then((res)=>{console.log(res);return new Promise((resolve,reject)=> {console.log('Something');resolve(4);})})

console.log("When?")

在输出“什么时候?”正在首先打印.. 现在我不明白这怎么可能,因为第一个回调将只在大约 10 秒内运行,只有在那之后,回调才会返回一个 Promise,它将运行第二个 then ? 也许我不明白 then 的回调如何“与”then 函数一起使用。 我认为 then 实现看起来有点像:

then(callback){
 let value= callback();
 if(value is promise){
     return value;
 }

 return Promise.resolve(value)
}

【问题讨论】:

    标签: javascript asynchronous


    【解决方案1】:

    这是因为promise中的代码是异步的,异步代码总是在所有同步代码都执行完之后才执行。

    在您的示例中,您有 2 条同步指令,第一行用于设置承诺链和 console.log。因此,首先 JavaScript 设置了 Promise,然后记录 When。只有在此之后,它才会一一解决承诺。

    如果您想让您的代码按照您的预期运行,您可以将其包装到 async function 中,然后使用 await 关键字停止同步代码的执行,直到解决承诺:

    //async is actually creating a promise under the hood for you
    async function imAsyncFunction () {
      // await will make sure that before proceeding to the next 
      // synchronous instruction (the console.log) the promise chain is resolved
    
      await Promise.resolve('333')
        .then((res)=>{console.log(res);return new Promise((resolve,reject)=> {setTimeout(function(){console.log('Timeout');resolve(1);},10000);console.log('Something');})})
        .then((res)=>{console.log(res);return new Promise((resolve,reject)=> {console.log('Something');resolve(2);})})    
        .then((res)=>{console.log(res);return new Promise((resolve,reject)=> {console.log('Something');resolve(3);})})
        .then((res)=>{console.log(res);return new Promise((resolve,reject)=> {console.log('Something');resolve(4);})});
    
      console.log("When?");
    }
    
    imAsyncFunction();
    
    // the log produced will be:
    
    // 333
    // Something
    // Timeout
    // 1
    // Something
    // 2
    // Something
    // 3
    // Something
    // When?
    

    more info on async / await

    【讨论】:

    • 我对你的答案投了赞成票,但由于它没有 100% 回答我的问题,我不想批准它。非常感谢!
    • 不客气!让我知道尚不清楚的地方,我可以对其进行扩展
    【解决方案2】:

    好问题。答案是评估 JavaScript 的事件循环。简而言之,有微任务和宏任务。控制台日志是宏任务,promise 是微任务。事件循环首先处理宏任务,然后是微任务。

    如需更深入的解释,请参阅:https://medium.com/javascript-in-plain-english/javascript-event-loop-y-promises-951ba6845899

    问题中有一段代码几乎相同。搜索console.log('start'); 即可找到。

    【讨论】:

    • 感谢您的回答。但是我很难理解 `return Promise.resolve(value)` 行是如何运行的。也许我需要找到一种方法来更清楚地提出问题。同时我投票赞成你的答案,因为我从中学到了
    【解决方案3】:

    看来您是 Javascript 新手。我也是,这让我很困扰。 console.log 将始终首先打印,因为它不在“then”内。 Js 将异步运行日志,这意味着它不会等待 promise 完成。要解决此问题或更好地解决此问题,请使用 .then 中的日志或使用 Promise.all(promiseName).then(log here)。

    希望我能有所帮助! 这可能也有帮助https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

    PS:我的第一个答案,如果我做错了什么,请告诉我:p

    【讨论】:

    • 首先谢谢你..你很棒..但我不想解决我想理解的问题。您发送给我的链接,我熟悉,阅读并尽可能多地从那里获取..但仍然无法理解then的实现,尽管我花了很多时间阅读和“玩”它
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-25
    • 1970-01-01
    • 2014-12-25
    • 1970-01-01
    • 2017-11-27
    • 1970-01-01
    • 2020-02-19
    相关资源
    最近更新 更多