【问题标题】:High level deferred/promise advice高级延迟/承诺建议
【发布时间】:2012-12-10 22:34:26
【问题描述】:

我有以下具有以下结构的代码:

doSomething '/', ->
  waitForthis '#e', ->
    waitForSomethingElse '#el', ->
      #actually do it

如果我想使用延迟/承诺是这样的:

doSomething().then(waitForthis).then(waitForSomethingElse);

我将在哪里创建 deferred,然后每个都返回一个 promise?

我只是在寻找一些粗略的建议来帮助我入门。

我可能会为此使用 jquery deferreds。

【问题讨论】:

    标签: javascript


    【解决方案1】:

    (假设 jQuery)

    为了确保链接,每个步骤都需要返回一个承诺。

    then() 就是这样做的,所以这里没问题。

    doSomething() 也需要返回一个承诺。你可以通过让 doSomething() 创建一个 deferred 并返回它的 Promise 来做到这一点。

    一些 jQuery 函数已经包含了一个 deferred,你可以直接用 then() 链接它们。例如:

    $.ajax(...).then(...)
    

    查看this article 了解更多详情和实例。

    【讨论】:

      【解决方案2】:

      如果您正在寻找类似的东西:

      Send request A
      when A returns,
      Send request B(result a)
      when B returns,
      Do C(response b)
      

      然后你需要让每一个都成为一个promise,并且你需要注意闭包(因为你不能从回调中收集返回值)。

      a_done = something_that_returns_a_promise();
      a_done.then(function (a_result) {
          var b_done = something_that_returns_a_promise(a_result);
          b_done.then(function (b_result) { do_C(b_result); });
      });
      

      如果您正在寻找类似的东西

      Send request A
      Send request B
      
      when A && B return,
      Do C
      

      然后你会看到一个函数,它接受一些承诺,并返回一个承诺。

      a = something_returning_a_promise();
      b = something_returning_a_promise();
      a_and_b_done = when(a, b);
      
      a_and_b_done.then(function (result1, result2) { do_c(result1, result2); })
                  .then(show_results);
      

      做类似的事情

      a_done.then(fillRows).then(showResults);
      

      不允许您进行多个异步调用... ...它的作用是让您一个接一个地链接一堆同步任务(或者在它们到达的顺序无关紧要的情况下进行异步调用完全)。

      .then
      

      .done
      

      或其他什么,并没有做任何特别的事情——它将一个任务添加到一个数组中。
      当异步承诺返回时(或者如果它已经返回并已解决),它只是按顺序遍历该列表,并触发所有回调,传递它解决的任何数据(并调用“成功”或“失败” " 回调,基于操作的成功)。

      因此,每个异步回调都需要一个 Promise,如果您尝试将回调链接在一起,您仍然需要将每个回调包装在一个闭包中(该闭包会将结果传递给构建下一个 Promise 的任何对象)。

      我在这里使用 jQuery $.Deferred()deferred.promise()deferred.resolve()deferred.reject()promise.done()promise.fail()$.when()
      其他库可能有不同的术语,但行为相似。

      var ImageLoader = function (name, format) {
          var loading = $.Deferred(),
      
              img = new Image(),
              url = name + (format || ".png");
      
          img.onload = function () {
              loading.resolve(img);
          };
      
          img.onerror = function () {
              loading.reject("Image failed to load:" + name);
          };
      
          img.src = url;
      
          return loading.promise();
      };
      
      
      var imgLoaded = ImageLoader("//mysite.com/myimg");
      
      imgLoaded.done(function () { console.log("img 1 loaded"); });
      imgLoaded.fail(function (msg) { console.log(msg); });
      
      var img2Loaded = ImageLoader("//yoursite.com/yourimg", ".jpg");
      img2Loaded.done(function () { console.log("img 2 loaded"); });
      img2Loaded.fail(function (msg) { console.log(msg); });
      
      
      var showImages = function (img1, img2) {
          document.body.appendChild(img1);
          document.body.appendChild(img2);
      };
      
      var both_loaded = $.when(imgLoaded, img2Loaded);
      both_loaded.done(showImages);
      

      这是一个凌乱而令人费解的例子,但与其让它变得优雅,我想我会尝试以一种显示所有部分的方式来编写它。

      【讨论】:

        【解决方案3】:

        类似这样的:

        doSomething().then(waitForthis).then(waitForSomethingElse);

        应该是

        doSomething('/').then( function() {
            return waitForthis('#e');
        }).then( function() {
            return waitForSomethingElse('#el');
        });
        

        或者你使用.bind()

        我将在哪里创建 deferred,然后每个都返回一个 promise?

        是的,每个函数都会返回一个承诺。在 jQuery 中,“Deferred”是延迟对象的构造函数,调用“promise()”返回的对象只有 addCallback 函数,不暴露触发方法。只需查看the docs 及其众多示例即可。

        【讨论】:

          猜你喜欢
          • 2015-03-08
          • 1970-01-01
          • 2015-03-27
          • 2023-03-21
          • 1970-01-01
          • 1970-01-01
          • 2013-09-11
          • 2016-12-08
          相关资源
          最近更新 更多