使用$ http.then()和$ q.all()将并行和链接请求进行角度组合

gre*_*zap 26 javascript promise angularjs

我有一组相当复杂的API调用,我试图尽可能优雅和高效.我理解如何使用服务的promise api $http来链接请求,以及如何使用$q服务并行地发出请求.但是对于这个特定的API工作流程,我需要同时做这两点

以下是高级API流程的示例:

  • /dog/<dog_id>
    • /breed/<breed_id>
      • /food/<food_id>
  • /cat/<cat_id>
  • /turkey/<turkey_id>
  • /fish/<fish_id>

第一层请求都有已知的ID.然而,<breed_id>需要使/breed呼叫必须从解析/dog响应,并<food_id>作出必要的/food呼叫必须从解析/breed响应.所以/dog,/breed/food所有需要进行链接.但是/cat,/turkey并且/fish可以与整个/dog链并行地制造.

我现在得到的(它工作正常)是两组独立的请求.如何改进此流程?有没有办法以一种导致单个承诺执行的方式组合两个堆栈.then()

var dogId = '472053',
    catId = '840385',
    turkeyId = '240987',
    fishId = '510412';

var myData = {};

var firstSetComplete = false,
    secondSetComplete = false,
    returnData = function() {
        if (firstSetComplete && secondSetComplete) {
            console.log("myData.dog", myData.dog);
            console.log("myData.dog.breed", myData.dog.breed);
            console.log("myData.dog.food", myData.dog.food);
            console.log("myData.cat", myData.cat);
            console.log("myData.turkey", myData.turkey);
            console.log("myData.fish", myData.fish);
        }
    };

// first call set
$http.get('http://example.com/dog/' + dogId)
.then(function(response) {
    myData.dog = response.data;
    return $http.get('http://example.com/breed/' + response.data.breed_id);
})
.then(function(response) {
    myData.dog.breed = response.data;
    return $http.get('http://example.com/food/' + response.data.food_id);
})
.then(function(response) {
    myData.dog.food = response.data;

    firstSetComplete = true;
    returnData();
});

// second call set
$q.all([
    $http.get('http://example.com/cat/' + catId),
    $http.get('http://example.com/turkey/' + turkeyId),
    $http.get('http://example.com/fish/' + fishId)
])
.then(function(responses) {
    myData.cat = responses[0].data;
    myData.turkey = responses[1].data;
    myData.fish = responses[2].data;

    secondSetComplete = true;
    returnData();
});
Run Code Online (Sandbox Code Playgroud)

dta*_*enc 47

您可以像这样传递第一个链:

$q.all([
    $http.get('http://example.com/cat/' + catId),
    $http.get('http://example.com/turkey/' + turkeyId),
    $http.get('http://example.com/fish/' + fishId),
    $http.get('http://example.com/dog/' + dogId)
    .then(function(response) {
         myData.dog = response.data;
         return $http.get('http://example.com/breed/' + response.data.breed_id);
     })
     .then(function(response) {
         myData.dog.breed = response.data;
         return $http.get('http://example.com/food/' + response.data.food_id);
     })
     .then(function(response) {
         myData.dog.food = response.data;
         return myData;
     })
])
.then(function(responses) {
    myData.cat = responses[0].data;
    myData.turkey = responses[1].data;
    myData.fish = responses[2].data;

    secondSetComplete = true;
    returnData();
});
Run Code Online (Sandbox Code Playgroud)

狗的承诺链最终会返回一个单一的承诺,当最后一个then被调用时它会被解决,并且它会从最终函数的结果中解析出来.所以没有理由不能将它嵌入你的$q.all()通话中.