2013-11-27 1 views
24

У меня довольно сложный набор вызовов API, и я стараюсь сделать это как можно более элегантно и качественно. Я понимаю, как использовать обещание api службы $http для запросов на цепочку и как использовать службу $q для выполнения запросов параллельно. Но для этого конкретного рабочего процесса API мне нужно сделать и то, и другое.

Ниже приведен пример потока API высокого уровня:

  • /dog/<dog_id>
    • /breed/<breed_id>
      • /food/<food_id>
  • /cat/<cat_id>
  • /turkey/<turkey_id>
  • /fish/<fish_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(); 
}); 
+2

может присваивать переменную очень первому запросу и включать эту переменную в '$ q.all()' array – charlietfl

ответ

44

Вы можете пройти в первой цепи, как так:

$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(); 
}); 

Это большая цепь обещаний для собак заканчивается возврат одного обещания, что не будет решен, когда последний then называется, и она решена с результат этой конечной функции. Поэтому нет причин, по которым вы не можете вложить его в свой вызов $q.all().

+0

Я использовал это, но в конечном итоге он вызывал все сервисы для каждого '.then' внутри скобок (возможно, мой кофейник был неправ). Я исправил это, поставив каждый '.then' после своего соответствующего вызова $ http, а окончательный' .then' работал без изменений. –

+0

Будет ли это каждый пообещать подряд или все параллельно? – f1lt3r