2016-11-14 72 views
0

在我開始之前,我想提一下,我沒有太多關於JavaScript中的promise/deferred對象的經驗。

我試圖實現的是當用戶點擊一個按鈕,它運行多個$.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函數都會返回一個promise,您可以直接使用它們。

這是我會怎麼寫代碼:

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錯誤而丟失。
  • 您應該使用jQuery的.text()(而不是.html())來設置文本值。
2

不需要調用apply使用Promise.all

該執行承諾的陣列,並返回一旦所有已經完成。

所以,你的代碼將變成:

$("#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上下文中,推薦'$ .when'比'Promise.all'更好。它的工作原理是一樣的(除了你需要'.apply()',因爲它需要一個參數列表,而不是一個數組),但它也適用於沒有本地承諾支持的瀏覽器。 – Tomalak

+0

那麼我會在'connect'方法中返回什麼?延期的對象或...? @Tomalak – ThePerplexedOne

+0

您將返回Ajax調用結果('return $ .getJSON(...))') - 這些已經在jQuery中有了承諾,你根本不需要那個「新的Promise()」調用。 – Tomalak