2014-05-09 19 views
7

Tôi đang viết một dịch vụ Angular.js để lấy một số nguồn cấp dữ liệu JSON. Ban đầu, dịch vụ không biết/có bao nhiêu tài nguyên để yêu cầu; chúng phụ thuộc vào các id được trả về bởi một yêu cầu khác.Javascript Góc: làm thế nào để chuỗi số lượng không rõ các lời hứa

Tôi đang gặp phải sự đau đầu khi yêu cầu dịch vụ $http cùng nhau. Có một mô hình thường được sử dụng để làm điều này?

Tôi đã thử kỹ thuật Array.reduce được đề xuất trên một chuỗi khác nhưng đã gặp sự cố khi đồng bộ hóa id và dữ liệu được yêu cầu.

Đây là những gì tôi có cho đến nay. Có ai có bất cứ đề nghị?

aService.factory('dummy', function($http){ 
    // Dummy resources. 
    var resources = [ 
     'http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js', 
     'http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js', 
     'http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js' 
    ]; 
    return { 
     data: function(callback){ 

      var jquerySources = [] 

      var promiseChain = $http({method: 'GET', url: resources[0]}); 
      var l = resources.length 
      for (var i = 1; i < l; i++){ 
       promiseChain.then(function(data){ 

        jquerySources.push({ 
         url: resources[i], 
         source: data 
        }); 

        promise_chain = $http({method: 'GET', url: resources[i]}); 
        if (i === l){ 
         return callback(jquerySources); 
        } 
       }); 
      } 
     } 
    } 
}); 

Thankyou.

+0

Bạn có thực sự cần để nạp mỗi tài nguyên lần lượt? Nếu không, bạn có thể không chỉ bắn ra nhiều yêu cầu và sau đó chờ đợi cho tất cả các lời hứa sẽ được giải quyết? – codemonkey

+0

Bạn có cần chúng thực hiện tuần tự hoặc chúng có thể chạy song song không? –

Trả lời

6

Nếu bạn cần thực hiện yêu cầu tuần tự, bạn sẽ tạo lời hứa mà bạn có thể sử dụng làm người đứng đầu chuỗi. Sau đó, bạn có thể chuỗi $ http gọi lên đến đầu đó và giải quyết lời hứa đầu:

aService.factory('seq', function($http, $q){ 
    // Dummy resources. 
    var resources = [ 
     'http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js', 
     'http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js', 
     'http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js' 
    ]; 
    var deferred = $q.defer(); 
    var resourcePromise = deferred.promise; 
    var res = []; 
    angular.forEach(resources, function(resource){ 
     return resourcePromise.then(function(){ 
     return $http({ method: 'GET', url: resource }); 
     }).then(function(data){ 
     res.push({res: resource, data : data}); 
     }); 
    }); 

    deferred.resolve(); 

    return { 
     getResource: resourcePromise.then(function(){ 
      return res; 
     }) 
    }; 
}); 

nhưng nếu yêu cầu sẽ song song - sau đó nó sẽ là giải pháp đơn giản hơn. Chỉ cần một loạt các lời hứa và chỉ cần gọi hàm $ q.all để chờ giải quyết mọi lời hứa.

aService.factory('par', function($http, $q){ 
    // Dummy resources. 
    var resources = [ 
     'http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js', 
     'http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js', 
     'http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js' 
    ]; 
    var promises = []; 
    var res = []; 
    angular.forEach(resources, function(resource){ 
     promises.push(
     $http({ method: 'GET', url: resource }).then(
      function(data){ 
      res.push({res: resource, data : data}); 
      }) 
     ); 
    }); 

    return { 
     getResource: $q.all(promises).then(function(){ 
      return res; 
     }) 
    }; 
}); 

Cũng lưu ý rằng trong cả hai trường hợp, chúng tôi có mảng res để thu thập kết quả yêu cầu.

EDIT: Plunker with example

+0

Tôi chỉ đang tìm kiếm một cái gì đó tương tự, và đây là tuyệt vời Oleksii. Một chút câu hỏi về nông dân, nhưng sau đó tôi đã cố gắng đưa dữ liệu đó vào một bộ điều khiển và gặp rắc rối. Tôi có thể console.log dữ liệu ra trong chức năng $ http trong nhà máy, nhưng không thể có được đầu ra trong json vào một phạm vi var trong một bộ điều khiển. Bạn có bất cứ đề nghị về cách tốt nhất làm điều này? –

+0

Có, bạn cần sử dụng hàm .then() sau khi gọi một dịch vụ. Tôi vừa thêm plunker với ví dụ cho câu trả lời của tôi, hãy nhìn vào nó. –

+0

rực rỡ, cảm ơn Oleksii rất nhiều, tôi thực sự đánh giá cao nó. Tôi vừa mới bình chọn câu trả lời của bạn. Cảm ơn đã giúp đỡ. –

2

Bạn thực sự có thể làm điều này với giảm:

var chain = resources.reduce(function (sourcesPromise, url) { 
    return sourcesPromise.then(function (sources) { 
     return $http({method: 'GET', url: url}) 
     .then(function (data) { 
      sources.push({url: url, source: data}); 

      return sources; 
     }); 
    }); 
}, $q.when([])); 

chain.then(function (sources) { 
    // [{url, source}, ...] 
}); 

dựa trên dựa trên How to chain a variable number of promises in Q, in order?

Các vấn đề liên quan