AngularJS - รอให้การสืบค้นทรัพยากรหลายรายการเสร็จสมบูรณ์


105

ฉันมีโรงงานเดียวที่กำหนดด้วย ngResource:

App.factory('Account', function($resource) {
    return $resource('url', {}, {
        query: { method: 'GET' }
    });
});

ฉันโทรหลายครั้งไปยังวิธีการสืบค้นที่กำหนดไว้ในโรงงานนี้ การโทรอาจเกิดขึ้นแบบอะซิงโครนัสได้ แต่ฉันต้องรอให้ทั้งสองสายเสร็จสิ้นก่อนดำเนินการต่อ:

App.controller('AccountsCtrl', function ($scope, Account) {
    $scope.loadAccounts = function () {
        var billingAccounts = Account.query({ type: 'billing' });
        var shippingAccounts = Account.query({ type: 'shipping' });

        // wait for both calls to complete before returning
    };
});

มีวิธีดำเนินการกับโรงงาน AngularJS ที่กำหนดด้วย ngResource คล้ายกับฟังก์ชัน $ .when () ของ jQuery หรือไม่? ฉันไม่ต้องการเพิ่ม jQuery ในโครงการปัจจุบันของฉัน

คำตอบ:


202

คุณจะต้องใช้คำสัญญาและ $ q.all ()()

โดยทั่วไปคุณสามารถใช้เพื่อรวมทรัพยากร $ หรือการโทร $ http ทั้งหมดของคุณได้เนื่องจากเป็นการคืนสัญญา

function doQuery(type) {
   var d = $q.defer();
   var result = Account.query({ type: type }, function() {
        d.resolve(result);
   });
   return d.promise;
}

$q.all([
   doQuery('billing'),
   doQuery('shipping')
]).then(function(data) {
   var billingAccounts = data[0];
   var shippingAccounts = data[1];

   //TODO: something...
});

17
ทรัพยากรไม่คืนสัญญา แต่จะส่งคืนวัตถุที่จะเติมเต็มในอนาคต อย่างไรก็ตามในเวอร์ชัน 1.1.3 ที่ไม่เสถียรทรัพยากรยังมี$thenคุณสมบัติ แต่ไม่เปิดเผยวัตถุสัญญาใด ๆ การเปิดเผย$promiseอย่างสมบูรณ์จะอยู่ใน 1.1.4
Umur Kontacı

@ UmurKontacıน่าเสียดายที่นี่ไม่ใช่เชิงมุม 1.1.4!
nh2

รายละเอียดเกี่ยวกับทรัพยากรไม่เป็นสัญญาปัญหาสามารถพบได้ในเธรดนี้และในคำขอดึงนี้
2

1
คำตอบนี้แสดงวิธีการเขียนเมื่อดำเนินการแล้ว
2

3
คำตอบของคุณมีประโยชน์มากและฉันเชื่อว่านี่เป็นวิธีที่สมเหตุสมผลที่สุดในการแปลงทรัพยากรเป็นสัญญาในเชิงมุมปัจจุบัน การเพิ่มในเอกสาร$qที่คุณเชื่อมโยงอาจเป็นประโยชน์ซึ่งจะรับประกันได้ว่าอาร์เรย์ผลลัพธ์อยู่ในลำดับเดียวกับอาร์เรย์สัญญา
nh2

20

ฉันคิดว่าทางออกที่ดีกว่าคือ:

$q.all([
   Account.query({ type: 'billing' }).$promise,
   Account.query({ type: 'shipping' }).$promise
]).then(function(data) {
   var billingAccounts = data[0];
   var shippingAccounts = data[1];

   //TODO: something...
});

1
สำหรับฉันทำงานโดยไม่มี $ สัญญาในตอนท้าย ... เช่นเดียวกับ: Account.query ({type: 'billing'}), Account.query ({type: 'shipping'})
georgeos

12

วิธีแก้ปัญหาจาก Ben Lesh ดีที่สุด แต่ยังไม่สมบูรณ์ หากคุณต้องการจัดการเงื่อนไขข้อผิดพลาด - และใช่คุณทำ - คุณต้องใช้catchวิธีการบนสัญญา API ดังนี้:

$q.all([
   doQuery('billing'),
   doQuery('shipping')
]).then(function(data) {
   var billingAccounts = data[0];
   var shippingAccounts = data[1];

   //TODO: something...

}).catch(function(data) {

   //TODO: handle the error conditions...

}).finally(function () {

  //TODO: do final clean up work, etc...

});

หากคุณไม่กำหนดcatchและคำสัญญาทั้งหมดของคุณล้มเหลวthenวิธีการนั้นจะไม่ดำเนินการและอาจทำให้อินเทอร์เฟซของคุณอยู่ในสถานะที่ไม่ดี

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.