2016-10-05 2 views
0

У меня возникла проблема, когда контроллер вызывает функцию getMyList службы, но myLists еще не заполняется, поскольку вызов $ http занимает некоторое время.

Как решить эту проблему?

Вот мой фрагмент кода:

Сервис

app.factory('myService', function($http) { 
    var myList = []; 

    $http.get("http://myService/json.data").then(function (resp) { 
     myLists = resp.data; 
    }); 

    return { 
     getMyList: function (name) { 
      for (var i = 0; i < myLists.length; i++) { 
       if (myList[i].name == name) { 
        return myLists[i]; 
       } 
      } 
     } 
    } 
} 

Контроллер:

app.controller('MainCtrl', function(myService,$scope) { 
    var testName = "test" 
    myService.getMyList(testName).then(function(resp) { 
     // do something with resp data 
    }); 
}); 
+0

у вас есть какие-либо маршрутизатор? Какой из них? – Hitmands

+0

У меня нет маршрутизатора. Но от контроллера мне нужно вызвать myService.getMyList, который возвращает мне список из кэшированных myLists – SimpleCoder

ответ

2

Сначала необходимо исправить опечатки, и выбрать лучший именование. Тогда вам необходимо вернуть обещание элемент, а не элемент (это то, что ожидает, что контроллер, кстати):

app.factory('myService', function($http) { 
    // this defines a promise which, when resolved, contains an array of elements 
    var listPromise = $http.get("http://myService/json.data").then(function(resp) { 
     return resp.data; 
    }); 

    return { 
     // this returns a promise which, when resolved, contains the element with the given name 
     getElementFromList: function(name) { 
      return listPromise.then(function(list) { 
       return list.filter(function(element) { 
        return element.name === name; 
       })[0]; 
      }); 
     } 
    }; 
}); 
+0

ok.это самый близкий ответ на мой первоначальный вопрос. Я все еще получаю resp undefined в моем классе контроллера, когда вызываю myService.getElementFromList (testName). Then (function (resp)) {// что-то делает} – SimpleCoder

+0

Тогда у iyou, вероятно, нет ни одного элемента в списке с этим именем. Что происходит при отладке? –

0

Каждый HTTP вызов возвращает в угловой с promise, поэтому в службе только обратный вызов HTTP и он возвращает promise.

Тогда в контроллере вы можете использовать then и error обратного вызова для обработки ответа от вызова service или api.

Фабрика:

app.factory('myService', function($http) { 
    var myList = []; 
    return { 
     getMyList: function (name) { 
      $http.get("http://myService/json.data") 
     } 
    } 
} 

Контроллер:

app.controller('MainCtrl', function(myService,$scope) { 
    var testName = "test" 
    myService.getMyList() 
    .then(function successCallback(resp) // Success call back 
    { 
      if(resp.data) 
      { 
      myLists = resp.data; 
      for (var i = 0; i < myLists.length; i++) { 
       if (myList[i].name == testName) { // you can use your testName here itself. 
        return myLists[i]; 
       } 
      } 

      } 
    }, 
    function errorCallback(resp) // Error call back 
    { 
     console.log(resp) 
    }); 
}); 
0

Если вы используете какой-то реализации маршрутизатора на стороне клиента: взглянуть на Route.Resolve что оба Ui.Router и ngRoute реализации.

Если у вас нет маршрутизатора, то есть небольшой трюк, который вы можете сделать ... Просто верните ссылку на объект с вашего завода и, когда произойдет разрешение, заполните этот объект ожидаемым значением :

angular 
 
    .module('test', []) 
 
    .constant('API', 'https://jsonplaceholder.typicode.com') 
 
    .factory("PostResolved", function($http, API) { 
 
    var result = []; 
 
    $http 
 
     .get(API + '/posts/1') 
 
     .then(function(response) { 
 
     result.push(response.data); 
 
     }) 
 
    ; 
 
    
 
    return result; 
 
    }) 
 

 
    .controller('TestCtrl', function($scope, PostResolved) { 
 
    $scope.posts = PostResolved; 
 
    }) 
 
;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> 
 

 
<section ng-app="test"> 
 
<article ng-controller="TestCtrl"> 
 
    <div ng-repeat="post in posts"> 
 
    <h1 ng-bind="post.title"></h1> 
 
    </div> 
 
</article> 
 
</section>

0

Почему бы не использовать что-то вроде ниже:

app.factory('myService', function($http) { 
 
    return { 
 
     getMyList: function (name) { 
 
      var myList = []; 
 
      $http.get("http://myService/json.data").then(function (resp) { 
 
       myLists = resp.data; 
 
      }); 
 
      
 
      scope.$evalAsync(function() { 
 
       for (var i = 0; i < myLists.length; i++) { 
 
        if (myList[i].name == name) { 
 
         return myLists[i]; 
 
        } 
 
       } 
 
      }); 
 
     } 
 
    } 
 
}

+0

Дело в том, что я хочу вызвать $ http.get вне метода getMyList. Мне нужно как-то кэшировать результат вызова http. Не уверен насчет $ evalAsync, когда я не сохраняю результат в области – SimpleCoder

+0

Я вижу, давайте попробуем использовать $ evalAsync для переноса myLists = resp.data; то, надеюсь, может помочь – Kerisnarendra

0

Мне удалось решить это, используя $ timeout. Любой, кто имеет лучшее предложение, дайте мне знать. Я не мог получить объем. $ EvalAsync работать

Сервис

app.factory('myService', function($http, $timeout) { 
    var lists = []; 

    $http.get("http://myService/json.data").then(function (resp) { 
     lists = resp.data; 
    }); 

    return { 
     getMyList: function (name) { 
      return $timeout(function() { 
       for (var i = 0; i < lists.length; i++) { 
        if (lists[i].name == name) { 
         return lists[i]; 
        } 
       } 
     }, 2000) 

    } 
} 

контроллер

app.controller('MainCtrl', function(myService,$scope) { 
    var testName = "test" 
    myService.getMyList(testName).then(function(resp) { 
     // do something with resp data 
    }); 
}); 
+0

Это неправильный ответ. ваш HTTP-ответ приходит до 2 секунд, поэтому его работа. Если требуется больше времени. – ram1993

+0

да, я знаю. Я открыт для предложений и улучшений – SimpleCoder

+0

Я создал [pen] (https://codepen.io/anon/pen/KgQgKk?editors=1011), как и ваш код. Я верю, что JBNizet дал правильный ответ. Другое решение - $ q. Но нет необходимости в этом. Как и в обоих случаях, вы собираетесь вернуть обещание. – ram1993