2015-08-17 2 views
2

Я пытаюсь получить два набора результатов из разных баз данных. Второй результат зависит от параметров, полученных из первого набора результатов. Я хочу, чтобы оба результата были возвращены перед продолжением. Глядя на некоторые другие вопросы, я думал, что, возможно, это будет работать:Angular - Как подождать два запроса, когда второй зависит от результатов от первого?

app.factory('myService',['$http','$q',function ($http, $q){ 

     function getDetails(scope){ 
      var paths = []; 
      return $q.all([ 
       $http.post('getdetails.php',{begDate:scope.begDate, endDate:scope.endDate}) 
       .then(function(response) { 
        angular.forEach(response.data,function(table,key){ 
         angular.forEach(table, function(row,key){ 
          paths.push(row.CURRENT_PATH); 
         }) 
        }) 
        return response; 
       }) 
      , 
       $http.post('coordtest.php', {paths: paths}) 
       .then(function(response) { 
        return response; 
       }) 
      ]); 

     } 

     return { 
      getDetails: getDetails 
     }; 
}]); 

Но результаты как получить возвращается в то время как пути по-прежнему пусто?

+1

'$ .q.all()' не собирается ждать второго запроса на первом ... они будут запускаться одновременно – charlietfl

+0

@charlietfl благодарю вас за ответ, можете ли вы рассказать мне, как я могу достичь этого поведение? –

+0

Посмотрите на [это] (http://stackoverflow.com/questions/32000037/resolve-and-q-all-issue/32000637#32000637), это должно помочь – user2718281

ответ

1

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

Что вы, кажется, на самом деле быть после имея один запрос (B) полагаются по результатам другого (A), но для возврата обещания B, чтобы его результаты могли быть использованы. Это возможно с помощью $q.defer создать обертку обещание, используя следующую закономерность:

var response = $q.defer(); 
$http.get('a').success(function(data){ 
    $http.get('b', data).then(response.resolve, response.reject); 
}); 
return response.promise; 

В вашем коде, это может выглядеть примерно так:

app.factory('myService',['$http','$q',function ($http, $q){ 

    function httpGetDetails(scope){ 
     return $http.post('getdetails.php',{ 
      begDate:scope.begDate, 
      endDate:scope.endDate 
     }); 
    }  

    function parseDetails(response){ 
     return response.reduce(function(parsedResults, table){ 
      var paths = table.map(function(row){ 
       return row.CURRENT_PATH; 
      }); 
      return parsedResults.concat(paths); 
     }, []); 
    } 

    function getDetails(scope){ 
     var result = $q.defer(); 

     var getDetailsRequest = httpGetDetails(scope); 

     getDetailsRequest.success(function(response){ 
      var paths = parseDetails(response); 

      $http.post('coordtest.php', {paths: paths}) 
        .success(result.resolve) // Both requests succeeded 
        .error(result.reject); // coordtest.php failed 
     }); 

     // getdetails.php failed. 
     // Consider sending params that make it more obvious which failed 
     getDetailsRequest.error(result.reject); 

     return result.promise; 
    } 

    return { 
     getDetails: getDetails 
    }; 
}]); 

Очевидно, что вы можете очистить функции немного, но это простой способ объединить обещания.

Идея состоит в том, что вы создаете долгосрочное обещание и вручную разрешаете его на основе результатов внутреннего (второго) запроса. Это похоже на возврат ответа coordtest на ваш завод myService, за исключением того, что это возможно (вы не можете синхронно возвращать обещание $http, выполненное в асинхронной функции, поэтому вы делаете и создаете обещание маскировки раньше времени).

+0

Большое вам спасибо за помощь. Это имеет смысл, хотя я могу использовать результаты обоих обещаний A и B после возвращения обещания от B? –

+0

Конечно, просто включите их в 'resolve' for ** B **. Что-то вроде '.success (function (dataB) {response.resolve ({resultsA: data, resultsB: dataB});});'. Мир - это ваша устрица в этой функции внутреннего успеха, отправляйте обратно любые данные, которые вы хотите. (Но, конечно, используйте более описательные имена переменных, чем я написал в реальной системе. Может быть, '{paths: paths, coords: coords}' или что-то еще). – DRobinson

+0

Отлично, еще раз спасибо! –

Смежные вопросы