0

I'm using Angular's $q service to return a promise. In my function the promise is resolved when I find the picture(a object) by a id(key value) which I'm searching in a array of pictures. I get the pictures if array is empty else I start searching. The function is working but I'm unable to make it into a promise.

My service method:

picturesService.getCurrentPic = function (pictureId) {

    console.log("process started, id: ", pictureId);
    if(picturesService.pictures.length == 0){
        console.log("empty");
        picturesService.getPictures().then(function(data){
            picturesService.pictures = data.data.children;
            picturesService.getCurrentPic(pictureId);
        });
    }else{
        var deferred = $q.defer();
        console.log("not empty");
        for (var i = picturesService.pictures.length - 1; i >= 0; i--) {
            if(picturesService.pictures[i].data.id == pictureId){
                console.log("found: ", picturesService.pictures[i].data);
                deferred.resolve(picturesService.pictures[i].data);
                break;
            };
        };
        return deferred.promise;
    };
};

Controller code:

picturesService.getCurrentPic(vm.pictureId).then(function(data){
    vm.currentPic = data;
    console.log("currentPic: ", vm.currentPic);
});

Error that I'm getting:

Cannot read property 'then' of undefined

y13uc162
  • 3
  • 1

2 Answers2

0

The first condition must also return a promise. You must also reject promise when an error occurs :

picturesService.getCurrentPic = function(pictureId) {

    var deferred = $q.defer();

    console.log("process started, id: ", pictureId);
    if (picturesService.pictures.length == 0) {
        console.log("empty");
        picturesService.getPictures().then(function(data) {
            picturesService.pictures = data.data.children;
            return picturesService.getCurrentPic(pictureId);

        }, function(error) {
            deferred.reject(error.message || error)
        });
    } else {
        console.log("not empty");
        var picture;
        for (var i = picturesService.pictures.length - 1; i >= 0; i--) {
            if (picturesService.pictures[i].data.id == pictureId) {
                picture = picturesService.pictures[i].data;
                console.log("found: ", picture);
                break;
            };
        };
        if (picture) {
            deferred.resolve(picture)
        } else {
            deferred.reject('picture not found: ' + id)
        }
    };

    return deferred.promise;
};

Then use it like this to handle errors :

picturesService.getCurrentPic(vm.pictureId).then(function(data){
    vm.currentPic = data;
    console.log("currentPic: ", vm.currentPic);
}, function(error) {
    console.log('error occured: ' + error);
});
Stephane Janicaud
  • 3,531
  • 1
  • 12
  • 18
  • So If I have to use recursion then I have to do so using promise? Also if I don't reject promise(agreed not a good practice) it should still work right? – y13uc162 Apr 06 '17 at 21:58
  • Using recursion is not a good practice, you should better chain promises : first load images THEN retrieve picture by id. Not rejecting promise is a really bad idea, don't do this ^^ – Stephane Janicaud Apr 06 '17 at 22:03
0

You are recursively calling the getCurrentPic inside and in the case when getPictures() returns empty data, this will keep going and it's not a good design. I would suggest to keep things simple by splitting the promises and chanining them.

For learning about promise chaining: http://solutionoptimist.com/2013/12/27/javascript-promise-chains-2/

For flattening promise chaining if it's get out of your hands: http://solutionoptimist.com/2013/12/27/javascript-promise-chains-2/

picturesService.pictures = [];
picturesService.getAllPictures() = function() {
    console.log('getting all pictures');
  picturesService.getPictures().then(function(data){
    console.log('populatiing the pictures array');
    picturesService.pictures = data.data.children;
  });
}

picturesService.getCurrentPic = function(pictureId) {
    var deferred = $q.defer();
  console.log('getting the picture information for ', pictureID);
  for (var i = picturesService.pictures.length - 1; i >= 0; i--) {
    if(picturesService.pictures[i].data.id == pictureId) {
      console.log("found: ", picturesService.pictures[i].data);
      deferred.resolve(picturesService.pictures[i].data);
    };
  };
  return deferred.promise;
}

// controller code
picturesService.getAllPictures().then(function() {
    picturesService.getCurrentPic(vm.pictureId).then(function(data){
      vm.currentPic = data;
        console.log("currentPic: ", vm.currentPic);
    });
});
TrueBlue
  • 321
  • 4
  • 5