2015-12-11 3 views
4

У меня есть сервис, обертывающий сторонний API, который я использую для извлечения данных в контроллер. Я хотел бы сделать некоторую обработку для поворота данных перед ее отображением, но я не могу работать, как это сделать после обещание завершено. До тех пор нет данных для обработки!Дождитесь завершения обещания перед обработкой результата

Я попробовал несколько различных способов, но ни один не кажется, работает:

angular.module('myApp').controller('myController', function ($scope, MyService) { 
    $scope.getData = function() { 
     MyService.getData(myParams) 
      .then(function (results) { 
       $scope.queryResults = results; 
       // Can't do processing here, data hasn't been retrieved yet 
      }, function (err) { 
       $scope.alerts.push({ msg: 'Unable to get data', type: 'danger' }); 
      }); 
    } 

    $scope.$watch('queryResults', function(newVals) { 
     // Can't do processing here either, this only fires at 
     // "$scope.queryResults = results;" 
     // above where "results" is still an empty array 
    }); 
}; 

И обслуживание:

angular.module('myApp').service('MyService', ['$q', function($q) { 
    return { 
     getData: function (params) { 
      var operation = $q.defer(); 
      ThirdPartyLibrary.getData(params, { callback: function(err, results) { 
       if (err == null) { 
        operation.resolve(results); 
       } else { 
        operation.reject(err, results); 
       } 
      }}); 
      return operation.promise; 
     } 
    } 
}]); 

Это должно быть довольно обычным делом хочу сделать, но Я не могу найти много на Google - хотя я, вероятно, искал неправильные вещи!

EDIT

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

angular.module('myApp').service('MyService', ['MyWrapperService', function(MyWrapperService) { 
    var getDataForFilter = function(myApi, filter) { 
     var processedResults = {}; 
     // This is the chain I'm having problems with 
     return MyWrapperService.getRelevantKeys(myApi, filter).then(MyWrapperService.getDetailsForKeys).then(function(results){ 
      //do some processing here 
      return processedResults; 
     }, function(errors) { 
      return errors; 
     }); 
    }; 

    return {getDataForFilter: getDataForFilter}; 
}]); 

angular.module('myApp').service('MyWrapperService', ['$q', function($q) { 
    var getRelevantKeys = function(myApi, filter) { 
     var operation = $q.defer(); 
     myApi.getKeys({'filter': filter, 'callback': function (err, results) { 
      if (err == null) { 
        // This does get called correctly, but not until after the rest of the chain has been called. 
       operation.resolve(myApi, results, filter); 
      } else { 
       operation.reject(err, results); 
      } 
     } 
    }; 
    var getDetailsForKeys = function(myApi, keys, filter) {    
     var operation = $q.defer(); 
     var promises = []; 
     var details = []; 
     var errors = []; 

     angular.forEach(keys, function (val) { 
      // Get the data for each key. ***When this is called, 'keys' is still undefined.*** 
      promises.push(getDataForKey(myApi, val, filter).then(function(result){ 
       details.push(result); 
      }, function(err, result) { 
       errors.push(err); 
      })); 
     }); 

     $q.all(promises).then(function() {operation.resolve(details);}, function() {operation.reject(errors)}); 
     return operation.promise; 
    }; 
    var getDataForKey = function(myApi, key, filter) { 
     var operation = $q.defer(); 
     myApi.getDetail(key, { 
      'filter': filter, 
      'callback': function(err, results) { 
       if (err == null) { 
        operation.resolve(myApi, results, activity); 
       } else { 
        operation.reject(err, results); 
       } 
      } 
     }); 
     return operation.promise; 
    }; 

    return { 
     getRelevantKeys: getRelevantKeys, 
     getDetailsForKeys: getDetailsForKeys, 
     getDataForKey: getDataForKey, 
    }; 
}]); 

К сожалению, API делает, что я пытаюсь сделать немного многословно, но я получаю все ключи базы данных, относящиеся к фильтру, а затем получить все значения для тех, затем переверните данные (комментарий в getDataForFilter), прежде чем передавать их обратно на контроллер для отображения. Я рад добавить больше комментариев, если что-то неясно.

(Кроме того, любая общая обратная связь по архитектуре это была бы оценена!)

+0

"* Это только срабатывает в' $ scope.queryResults = results; '*" именно то, что вы хотели, не так ли? Если 'results' - пустой массив, то это означает, что' getData' привел к пусту массива. – Bergi

+0

Я предполагаю, что это ваша служба, которая делает что-то странное, или вы просто не получаете никаких данных для вашего запроса. –

+1

Он возвращает данные, но требуется несколько секунд. 'then (function (results) {$ scope.queryResults = results;}' вызывается мгновенно с пустым массивом, который затем заполняется после завершения основного вызова API. – Mourndark

ответ

0

Так что я полностью переработан все, и теперь все это работает! Одной из проблем было забыть, что $q.resolve() и $q.reject() могут возвращать только один аргумент, когда я предположил, что могу просто вернуть столько аргументов, сколько захотелось с ними (как можно с анонимными функциями), а затем вызовы then() получили бы их все.

Если кто-то заинтересован, я выложу свой код после рефакторинга, но минимум мне нужно сделать, это заменить вызовы, как это:

operation.resolve(arg1, arg2, arg3); 

с этим:

operation.resolve({'arg1': arg1, 'arg2': arg2, 'arg3':arg3}); 

и настроить функции которые принимают эти аргументы соответствующим образом.

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