engineerKev
engineerKev

Reputation: 335

Angular JS using $resource and waiting for promise to be resolved

I wrote this service that uses $resource to fetch usernames using the github api

githubApiD3App.service('githubApiService', ['$resource', function($resource){
    this.GetuserNames = function(searchString){
        var githubAPI = $resource("https://api.github.com/search/users", {callback: "JSON_CALLBACK"}, {get: { method: "JSONP"}});

        return githubAPI.get({ q: searchString});
    };
}]);

In my controller I am doing this

$scope.githubData = githubApiService.GetuserNames($scope.searchString);

I know a promise is being returned but I can't seem to be able to make my service wait before returning the data or my controller wait for the data. As my code stands now I immediately get an empty object as a response. I've tried using success in my controller like so

scope.githubData = githubApiService.GetuserNames($scope.searchString).success(callback());

where in the callback I return the data. However that doesn't work. I've also tried using .$promise paired with .then in my service but that doesn't work either.

So with that said, what can I do so that $scope.githubData doesn't get assigned an empty object or waits for the response?

Upvotes: 0

Views: 550

Answers (3)

engineerKev
engineerKev

Reputation: 335

This is my answer to my question. It is not the perfect answer only because I was trying to handle promises incorrectly to begin with. This blog post helped me better understand promises and how to handle them properly.

In the controller of my app instead of assigning a scope variable w/e the promise returned, I did this

githubApiService.getUsernames($scope.searchString).then(function(results){

    $scope.returnedUsers = results.data.items.splice(start, deleteCount);

    console.log($scope.returnedUsers);
});

I've shortened the contents of my controller, but I basically handled all manipulation of the data inside the .then callback function. This line

$scope.returnedUsers = results.data.items.splice(start, deleteCount);

works to both set the variable in the controller, within the callback, and also to populate it with the necessary data so it can be outputed in my view when I did {{githubData}}. By doing everything inside the callback function I stopped getting any errors due to undefined variables. I was getting errors because when I did something like this

$scope.githubData = githubApiService.GetuserNames('engineerKev').then(function(results){
console.log(results.data.items[0]);
});
$scope.githubData.data.items.sort(sortFunction);

$scope.githubData would be an empty object with undefined properties.

So moral of the story, and please edit my answer if I still don't get promises, is to handle your promises inside the callback function in your controller.

Upvotes: 1

fikkatra
fikkatra

Reputation: 5792

This:

$scope.githubData = githubApiService.GetuserNames($scope.searchString);

is correct for 'normal' $resource usage. However, when combining $resource with JSONP, things could get a little funky. Try to do something like this (I added isArray and changed the action name to avoid potential conflicts with $resource.get):

githubApiD3App.service('githubApiService', ['$resource', function($resource){
    this.GetuserNames = function(searchString){
        var githubAPI = $resource("https://api.github.com/search/users", {callback: "JSON_CALLBACK"}, {getUsers: { method: "JSONP", isArray: true}});

        return githubAPI.getUsers({ q: searchString});
    };
}]);

Then in the controller:

githubApiService.GetuserNames($scope.searchString).$promise.then(function(users){
    $scope.githubData = users;
});

This is a good read on the subject: http://www.bennadel.com/blog/2610-using-jsonp-with-resource-in-angularjs.htm

Upvotes: 1

Amio.io
Amio.io

Reputation: 21565

Man, now I can't install $resource but I did a similar thing using $http.

Check this out:

githubApiD3App.service('githubApiService', ['$resource', function($resource){
    return $http.get("https://api.github.com/search/users?q=" + searchString);
    };
}]);

Then using then I handle the results:

scope.githubData = githubApiService.GetuserNames('engineerKev').then(function(results){
console.log(results.data.items[0]);
});

and print this:

{
  "total_count": 1,
  "incomplete_results": false,
  "items": [
    {
      "login": "engineerKev",
      "id": 3943145,
      "avatar_url": "https://avatars.githubusercontent.com/u/3943145?v=3",
      "gravatar_id": "",
      "url": "https://api.github.com/users/engineerKev",
      "html_url": "https://github.com/engineerKev",
      "followers_url": "https://api.github.com/users/engineerKev/followers",
      "following_url": "https://api.github.com/users/engineerKev/following{/other_user}",
      "gists_url": "https://api.github.com/users/engineerKev/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/engineerKev/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/engineerKev/subscriptions",
      "organizations_url": "https://api.github.com/users/engineerKev/orgs",
      "repos_url": "https://api.github.com/users/engineerKev/repos",
      "events_url": "https://api.github.com/users/engineerKev/events{/privacy}",
      "received_events_url": "https://api.github.com/users/engineerKev/received_events",
      "type": "User",
      "site_admin": false,
      "score": 40.398766
    }
  ]
}

Upvotes: 1

Related Questions