2016-11-14 7 views
0

私が始められる前に、私はJavaScriptの約束/遅延オブジェクトをあまり経験していないと言いたいと思います。

私が達成しようとしているのは、ユーザーがボタンをクリックし、複数の$.getJSONリクエストを実行し、レスポンスを処理し、それに応じてページを更新するときです。

私もこれらの要求のすべてが完了したときにユーザーに通知する必要があり、ここで私が話した最初の部分を処理し、私が持っているconnect方法は次のとおりです。

function connect(row) { 
    return new Promise(function(resolve, reject) { 
     var trees = $("#selectedTree").val(); 
     var employee_id = row.attr("rel"); 

     var columns = row.children(); 
     var emailColumn = $(columns[1]); 
     var firstNameColumn = $(columns[2]); 
     var lastNameColumn = $(columns[3]); 
     var jobTitleColumn = $(columns[4]); 
     var statusColumn = $(columns[5]); 
     var actionsColumn = $(columns[6]); 

     actionsColumn.html("<span class='spinner'><i class='fa fa-spinner fa-spin'></i></span>"); 
     $.getJSON("functions/connect_with.php", { 
      employee_id: employee_id, 
      trees: trees 
     }, function(response) { 
      emailColumn.html(response.message.person.email); 
      actionsColumn.html("<i class='text-success fa fa-check'></i>"); 
      if(response.success) { 
       firstNameColumn.html(response.message.person.name.givenName); 
       lastNameColumn.html(response.message.person.name.familyName); 
       jobTitleColumn.html(response.message.person.employment.title); 
      } 
      statusColumn.html("<i class='text-success fa fa-sitemap'></i>"); 
      resolve(true); 
     }); 
    }); 
} 

そして、これは何が起こるかです

$("#connectAll").click(function() { 
     alert("OFF WE GO"); 
     $(this).hide(); 
     var methods = []; 
     $(".staffMember input:checked").each(function(index, checkbox) { 
      checkbox = $(checkbox); 
      var row = checkbox.parents("tr"); 
      methods.push(connect(row)); 
     }); 
     $.when.apply($, methods).then(function() { 
      alert("WE DID IT MOM"); 
      $("#connectAll").show(); 
     }); 
    }); 

しかし、両方のアラートが互いの直後に送信され、完了するために要求を待っていない:ユーザーがクリックボタンが言いました。私はこれを行うための他の方法を試してきました。

+3

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all – Hackerman

+0

まあ、くそ。このトリックをしたようでした。ありがとう! – ThePerplexedOne

+0

本当に良いリンク@Hackerman、私はそれについて知らなかった – George

答えて

1

あなたは、すべてのコードでPromiseを使用する必要はありません - あなたはあなた自身の約束ライブラリをロードしている場合を除き、私はそれに対して助言、および、until all browsers support native promises

しかし、主な理由は、jQueryがこのタスクの十分な程度を約束していることです。すべてのjQuery Ajax関数は約束を返します。直接使用できます。

function connect($row) { 
    var columns = $row.children("td"); 
    $(columns[6]).html("<span class='spinner'><i class='fa fa-spinner fa-spin'></i></span>"); 

    return $.getJSON("functions/connect_with.php", { 
     employee_id: $row.attr("rel"), 
     trees: $("#selectedTree").val() 
    }).done(function (response) { 
     $(columns[1]).text(response.message.person.email); 
     if(response.success) { 
      $(columns[2]).text(response.message.person.name.givenName); 
      $(columns[3]).text(response.message.person.name.familyName); 
      $(columns[4]).text(response.message.person.employment.title); 
     } 
     $(columns[5]).html("<i class='text-success fa fa-sitemap'></i>"); 
    }).always(function() { 
     $(columns[6]).html("<i class='text-success fa fa-check'></i>"); 
    }); 
} 


$("#connectAll").click(function() { 
    $(this).hide(); 

    var calls = $(".staffMember input:checked").map(function() { 
     return connect($(this).parents("tr")); 
    }).toArray(); 

    $.when.apply($, calls) 
    .fail(function (jqXhr, status, error) { 
     // display or handle the error 
    }) 
    .always(function() { 
     $("#connectAll").show(); 
    }); 
}); 

サイドノート:

  • あなたはエラーハンドラを実装する必要がありスピナーを削除するか、ボタンが座るべきで復元(.fail(...)
  • コードここ

    は、私はあなたのコードを記述します方法です.always()ハンドラでは、断続的なAjaxエラーのためにページ機能が失われないようにします。

  • テキスト値を設定するには、.text().html()ではなく)を使用する必要があります。
2

よりもむしろPromise.all

apply使用を呼び出すこれは、一度すべて完了した約束とリターンの配列を実行します。

だからあなたのコードになるでしょう:

$("#connectAll").click(function() { 
    alert("OFF WE GO"); 
    $(this).hide(); 
    var methods = []; 
    $(".staffMember input:checked").each(function(index, checkbox) { 
    checkbox = $(checkbox); 
    var row = checkbox.parents("tr"); 
    methods.push(connect(row)); 
    }); 
    Promise.all(methods).then(values => { 
    alert("WE DID IT MOM"); 
    $("#connectAll").show(); 
    }).catch(reason => { 
    alert("MOM, SOMETHING WENT WRONG"); 
    }); 
}); 
+0

jQueryコンテキストでは、 'Promise.all'より' $ .when'を推奨する方がはるかに優れています。 (配列ではなくパラメータリストを期待しているので '.apply()'が必要な場合を除いては同じですが)ネイティブの約束をサポートしていないブラウザでも動作します。 – Tomalak

+0

次に 'connect'メソッドで何を返すのですか?遅延オブジェクトまたは...? @Tomalak – ThePerplexedOne

+0

あなたはAjax呼び出し結果を返します( 'return $ .getJSON(...) ') - それらはすでにjQueryで約束されているので、' new Promise() 'コールはまったく必要ありません。 – Tomalak

関連する問題