【问题标题】:Promise.all() and then() issuesPromise.all() 和 then() 问题
【发布时间】:2017-05-18 10:49:17
【问题描述】:

我对@9​​87654321@ 有一些问题

我正在尝试使用这个链:

Promise.all([
    this.newContainerLoading,
    this.gsapAnim()
])
.then(
    Promise.all([
        this.fadeOut.bind(this),
        this.preload.bind(this)
    ])  
)
.then(this.fadeIn.bind(this))

但由于某种原因,second Promise.all() 中的 2 个函数甚至没有被调用?例如 fadeOut()preload() 似乎根本没有被调用,并且链只是跳到最后的 then() 并执行 fadeIn()

关于我做错了什么有什么想法吗?

【问题讨论】:

    标签: javascript ecmascript-6 promise es6-promise


    【解决方案1】:

    您需要将fadeOutpreload 包装在一个函数中,以便在解决.all 时调用它们,否则将立即调用它们。

    下面的代码显示了一种正确的方法

    function newContainerLoading() {
      return new Promise((res) => {
        setTimeout(() => {
          console.log('newContainerLoading');
          res()
        }, 1000)
       })
     }
    
    function gsapAnim() {
      return new Promise((res) => {
        setTimeout(() => {
          console.log('gsapAnim');
          res()
        }, 1000)
       }) 
    }
    
    function fadeOut() {
        return new Promise((res) => {
        setTimeout(() => {
          console.log('fadeOut');
          res()
        }, 1000)
       })
    }
    
    function preload() {
      return new Promise((res) => {
        setTimeout(() => {
          console.log('preload');
          res()
        }, 1000)
       })  
    }
    
    
    function fadeIn() {
     console.log('fadeIn')
    }
    
    
    Promise.all([
        newContainerLoading(),
        gsapAnim()
    ])
    .then(()=> 
        Promise.all([
            fadeOut(),
            preload()
        ])  
    )
    .then(fadeIn)

    【讨论】:

    • 你能解释一下为什么我需要将第二个Promise.all() 包装在这样的函数中吗? Promise.all() 不会返回一个新的单个 Promise 对象吗?而且,如果您的示例中的匿名包装函数没有返回 Promise,它如何知道何时执行下一个 then()
    • 我刚刚测试了你的例子,它没有工作,和以前一样,第二个Promise.all()中的两个函数没有被调用
    • 我的主要困惑是为什么没有调用 preload()fadeOut() 函数 - 但那是因为我在 Promise.all() 中使用了 bind()
    【解决方案2】:

    bind 在这里用错了。 .bind(this) 的结果是绑定函数。它不会被调用,除非像this.fadeOut.bind(this)() 那样显式调用它。

    bind 与promise 一起使用的目的是使用绑定函数作为回调。 Promise.all 不接受回调,但 then 接受。而Promise.all 返回一个promise,所以它必须用箭头函数包装。应该是:

    Promise.all([
        this.newContainerLoading,
        this.gsapAnim()
    ])
    .then(() => 
        Promise.all([
            this.fadeOut(),
            this.preload()
        ])  
    )
    .then(this.fadeIn.bind(this))
    

    【讨论】:

    • 谢谢!这就是答案。混乱来自其他 then() 调用,其中包含 bind() - 但我现在看到 bind() 返回一个函数,这是 then() 所期望的,但 Promise.all() 想要一个 数组承诺,我需要通过调用函数fadeOutpreload来生成,而不是绑定它们。谢谢你:)
    • 不客气。请注意,您需要用箭头函数包装第二个 Promise.all,因为您需要在里面有词法 this。这应该不是问题,因为您使用的是 ES6。
    【解决方案3】:

    您应该在内部承诺中声明then部分并使用变量来存储父this,请参见以下内容:

    var self = this;
    
    var newContainerLoading = "dummy";
    function gsapAnim(){
      console.log("gsapAnim");
      return "gsapAnim";
    }
    function fadeOut(){
      console.log("fadeOut");
      return "fadeOut";
    }
    function preload(){
      console.log("preload");
      return "preload";
    }
    function fadeIn(){
      console.log("fadeIn");
      return "fadeIn";
    }
    
    Promise.all([
        this.newContainerLoading,
        this.gsapAnim()
    ])
    .then(values => {
          Promise.all([
              self.fadeOut(),
              self.preload()
          ]).then(values => {console.log(values)})
       }
    )
    .then(self.fadeIn.bind(self))

    如果你想保持链,你应该在第一个完成时调用最后一个 Promise,见如下:

    var self = this;
    
    var newContainerLoading = "dummy";
    function gsapAnim(){
      console.log("gsapAnim");
      return "gsapAnim";
    }
    function fadeOut(){
      console.log("fadeOut");
      return "fadeOut";
    }
    function preload(){
      console.log("preload");
      return "preload";
    }
    function fadeIn(){
      console.log("fadeIn");
      return "fadeIn";
    }
    
    Promise.all([
        this.newContainerLoading,
        this.gsapAnim()
    ])
    .then(values => {
          Promise.all([
              self.fadeOut(),
              self.preload()
          ]).then(self.fadeIn.bind(self))
       }
    )

    【讨论】:

    • values 部分是干什么用的?我需要那个吗?我对函数中的值不感兴趣,我只想在正确的时间调用它们,并在它们完成后解析Promise.all()
    • 另外,如果我运行你的 sn-p,“fadeIn”日志会输出“fadeOut”和“preload”值日志之前,对吗?
    • 是的,没错,每个回调函数(在then 方法中调用)都是异步的。因此,当计算第一个 then 时,返回一个新的 Promise,它也是异步的,因此它的执行立即开始(可能在嵌套 Promise 结束之前)。我希望它很清楚。
    • 请看我的更新,我添加了一个 sn-ps,您可以在其中看到如何在顺序链接中执行另一个 Promise。
    猜你喜欢
    • 1970-01-01
    • 2016-01-09
    • 2018-10-11
    • 1970-01-01
    • 2020-10-14
    • 2017-08-28
    • 2018-07-25
    • 2021-01-19
    • 2021-06-06
    相关资源
    最近更新 更多