【问题标题】:JavaScript Chaining Promises : Calling next promise before previous has finishedJavaScript Chaining Promises:在上一个完成之前调用下一个承诺
【发布时间】:2016-02-01 21:13:34
【问题描述】:

工具:JavaScript ES6

我还没有看到一个关于链接多个 Promise 以按顺序执行的语法的简洁的好答案。我认为对于所有承诺的新手来说,这将是解决棺材问题的好方法。 :)

我的问题是我想以同步顺序调用它getPosts--->getThreads--->initializeComplete()

这就是我正在做的事情。

userPromise.then(getPostsPromise).then(getThreadsPromise).then(initializeComplete());
  • userPromise 是我从另一部分代码返回的 Promise obj
  • getPostsPromise 返回一个 Promise 并获取服务器以获取帖子
  • getThreadsPromise 返回一个 Promise 并获取线程的服务器
  • initializeComplete 是一个回调,告诉我的程序它已初始化。

这里是链中的一个 Promise 示例:

var getPostsPromise = function(){
    //Firebase is just a simple server I'm using
    var firebasePostsRef = new Firebase("https://myfburl.firebaseio.com/posts");
    var postsRef = firebasePostsRef.child(localPlace.key);

    return new Promise(function(resolve, reject) {
      //Below is a Firebase listener that is called when data is returned
      postsRef.once('value', function(snap,prevChild) {
            var posts = snap.val();
            AnotherFile.receiveAllPosts(posts);
            resolve(posts);
        }); 
      });
}

但是initializeComplete()getPostsPromisegetThreadsPromise 有机会完成获取之前被调用。

为什么会发生这种情况以及如何编写要按顺序执行的 Promise?

【问题讨论】:

  • 你必须从你的承诺链中返回一些东西来等待完成每个
  • @Michael 如果有人不需要将任何东西转移到下一个承诺,他们只需要按顺序运行(顺便说一句,我应该将它添加到问题中吗?)
  • 没关系,什么都不做,只有返回部分很重要
  • then(()=>getPostsPromise).then...
  • 对于初学者,您可能想尝试从 initializeComplete() 中删除括号...

标签: javascript promise ecmascript-6 es6-promise


【解决方案1】:

initializeComplete 会立即被调用,因为您在将它传递给 then 时正在调用它。您必须省略括号,就像您为 getPostsPromisegetThreadsPromise 所做的那样

userPromise.then(getPostsPromise).then(getThreadsPromise).then(initializeComplete);

【讨论】:

  • 这似乎是一个简单的答案。
  • 这对我有用!谢谢大家的帮助。那么当方法返回一个新的 Promise 时,链中不需要返回值?
  • 是的,你的代码很好。只是有那个小括号错误。当你传入的函数返回一个 Promise 时,传入的下一个函数将等待该 Promise 被解析,并将传递你解析前一个 Promise 的值。如果您还没有html5rocks.com/en/tutorials/es6/promises,请查看这篇文章。感谢 Matthew 让我意识到这一点。
  • 方法的返回值是一个promise
  • 感谢你们@yts 和 Matthew,这对于最终需要它的其他人来说将非常有用。
【解决方案2】:

虽然 yts 的答案是正确的(问题是您调用的是 initializeComplete 而不是传递函数),但我宁愿对调用的格式稍有不同。让每个回调函数调用下一个函数有点违背 Promise 的设计。我宁愿每个函数都返回一个promise,然后在返回的promise上调用then

userPromise
.then(function(){
  return getPostsPromise()
}).then(function(){
  return getThreadsPromise()
}).then(function(){
  return initializeComplete();
});

或者传递实际返回的对象而不必做任何额外的中间处理:

userPromise
.then(getPostsPromise)
.then(getThreadsPromise)
.then(initializeComplete);

【讨论】:

  • 这个方法仍然是同步的,它会调用getPostsPromise,一旦这个promise被解决它就会调用getThreadsPromise,一旦这个promise被解决调用initializeComplete
  • 啊,是的,你是对的。如果那是 then 函数中返回的内容,我不知道等待承诺的魔法。酷 :) 编辑了我的答案。
  • 当我这样做时,我在 Promise 中“解决”的事情在下一个 Promise 中是未定义的。如何使用上述格式传递它?
  • 您可以为每个函数提供参数并将其传递给下一个函数。或者喜欢 userPromise.then(getPostsPromise)。这会将 userPromise 的响应传递给 getPostPromise
  • 如果您没有函数的自定义参数,那么没有理由比 yts 答案显示的更详细。这不会改变行为,只会编写更多代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-02
  • 1970-01-01
  • 1970-01-01
  • 2016-04-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多