function get (id, ignore) {
var deferred = $q.defer();
$http.get('v1/info/' + id, {
ignoreAuthModule: ignore
})
.success(function (data) {
deferred.resolve(data.data);
})
.error(function (reason) {
deferred.reject(reason.message););
});
return deferred.promise;
}
init();
function init(){
users.get($routeParams.id)
.then(function (data) {
if(data.has_something === 1){
$scope.hasSomething = true;
}else{
$scope.hasSomething = false;
}
});
}
I have a Service that get the information about user using promise and Fetching information from the service with init function
//if i call init function this should call two times one from function initialization and other i'm calling it from service
how can i stop two times calling api I mean it should call one time if already called
You're using the explicit promise creation antipattern here, and your code could be much simpler. Here is how you can use memoization to avoid requesting the same user twice:
.factory('users', ['$http', function ($http) {
var userPromises = {};
function get (id, ignore) {
if (!userPromises[id]) {
userPromises[id] = $http.get('v1/info/' + id, {
ignoreAuthModule: ignore
})
.then(function (data) {
return data.data;
})
.catch(function (reason) {
throw new Error(reason.message);
});
}
return userPromises[id];
}
return {
get: get
};
});
You can assign your deferred.promise to some variable and then return that variable, and before your http call just check whether that variable is already defined or not
function get (id, ignore) {
if (angular.isUndefined(user)) {
var deferred = $q.defer();
$http.get('v1/info/' + id, {
ignoreAuthModule: ignore
}).then(function(response) {
if (response.status == 200) {
deferred.resolve(response.data);
} else {
deferred.reject(response.data);
};
user = deferred.promise;
return user;
} else {
return user;
}
}
This way your api will get called only once.
Related
I'm doing this login exercise where users can login and post notes, and view the notes that they've posted. My problem is when I logout and login with a different user I see the notes from the previous user.
Here's an illustration:
I log in with a different user then this shows up:
I restart the page and the appropriate note shows up:
The controller for this:
exports.homeController = function ($scope, $location, $q, $users, $window, $notes, $http) {
var auth = function () {
var userInfo = $users.getUserInfo()
if (userInfo) {
return $q.when(userInfo)
} else {
return $q.reject({ authenticated: false })
}
}
$scope.userInfo = auth()
myNotes($scope.userInfo.$$state.value.accessToken) // I invoke my function to get the notes for each specific user but it doesn't seem to work.
$scope.logout = function () {
$users.logout()
.then(function (results) {
$scope.userInfo = null
$scope.myNotes = null
$location.path('/')
}, function (err) {
console.log(err)
})
}
$scope.notes = {
notes: ''
}
$scope.postNote = function () {
$notes.postNotes($scope.userInfo.$$state.value.accessToken, $scope.notes)
.then(function (result) {
$scope.myNotes.push($scope.notes)
$scope.notes = ''
}, function (err) {
console.log(err)
})
}
function myNotes (user_id) {
$notes.getMyNotes(user_id)
.then(function (result) {
console.log(result)
$scope.myNotes = result.data
}, function (err) {
console.log(err)
})
}
}
This is the app https://login-sys.herokuapp.com/
I've found your non-minified code for the services.
Based on that I think the problem is that you declare var deferred = $q.defer() one time in the $notes service.
I think it should be "renewed" every time the service methods are called:
function getMyNotes (user_id) {
var deferred = $q.defer();
$http.get('/api/myNotes/' + user_id + '?access_token=' + user_id)
.then(function (result) {
deferred.resolve(result)
}, function (err) {
deferred.reject(err)
});
return deferred.promise
}
Similarly in postNotes.
The second time you return the same promise with the same value, so your homeController's getMyNotes function will get the same result despite the $notes service making a new request.
In the $users service's logout and signup functions you are already using it correctly.
I am new to angularjs.I am using factories where i have written the fb login code.
And during the last step i am sending all the data to my server where the user is registered in my database and the token is sent.
Here is the code.
'use strict'
APP.factory('authenticationFactory',['ENV','$http','$rootScope', function (ENV,$http,$rootScope) {
return {
socialLogin:function(data){
return $http.post($rootScope.apiURL+'sociallogin',data).then(function (resp) {
if(resp.status == 200) {
return resp.data;
}
})
},
fbLogin: function () {
var FB = window.FB;
var scopes = 'public_profile,email';
var that = this;
FB.login(function (response) {
return that.facebookStatusChangeCallback(response);
}, {scope: scopes});
},
facebookStatusChangeCallback: function(response){
if (response.status === 'connected') {
// Logged into your app and Facebook.
var r = this.facebookApiRequest(response);
console.log(r);
} else if (response.status === 'not_authorized') {
// The person is logged into Facebook, but not your app.
console.log('Please log into this app.');
} else {
// The person is not logged into Facebook, so we're not sure if
// they are logged into this app or not.
console.log('Please log into Facebook.');
}
},
facebookApiRequest: function (authResponse) {
var that = this;
var r = FB.api('/me?fields=id,name,email,gender,first_name,last_name,age_range,link,birthday', function (response) {
var r = FB.api("/" + response.id + "/picture?height=720", function (pictureResponse) {
if (pictureResponse && !pictureResponse.error) {
/* handle the result */
response.profile_pic = pictureResponse.data.url;
response.access_token = authResponse.authResponse.accessToken;
response.provider = 'facebook';
response.devicetoken = '';
response.full_name = response.first_name+' '+response.last_name;
var r = that.socialPluginLogin(response).then(function (resp) {
return that.resp;
});
return r;
} else {
console.log('error while fatching fb pic');
}
});
console.log(r);
});
console.log(that);
},
socialPluginLogin : function (data) {
var resp = this.socialLogin(data).then(function (resp) {
return resp;
});
return resp;
}
};
}]);
I am calling the fbLogin() function from my controller. i need the response from the function socialLogin() so that i can change the state.
Where am i going wrong.??
The answer was pointing in the wrong direction, another try:
Your function fbLogin should return a promise, which can be resolved by socialLogin later. Since fbLogin doesn't return a thing, you don't receive any signal from the completed login.
See this:
// We add $q here
APP.factory('authenticationFactory',['ENV','$http','$rootScope','$q', function (ENV,$http,$rootScope,$q) {
var loginPromise;
return {
socialLogin:function(data){
return $http.post($rootScope.apiURL+'sociallogin',data).then(function (resp) {
if(resp.status == 200) {
// This is your connection to the controller
loginPromise.resolve(resp.data);
return resp.data;
}
})
},
fbLogin: function () {
var FB = window.FB;
var scopes = 'public_profile,email';
var that = this;
FB.login(function (response) {
return that.facebookStatusChangeCallback(response);
}, {scope: scopes});
// Create and return a promise
loginPromise = $q.defer();
// EDIT: My fault, return the promise:
return loginPromise.promise;
},
//...
And add this to the controller:
authenticationFactory.fbLogin().then(function(data){
// Check it out:
console.dir(data);
})
Additional things you should consider:
Define your functions in the function body, not in the return statement. You can eliminate that=this this way
Only return the API, not all the functions
Read up on promises, they are the way to go in the angular world. You might as well use callbacks, but those are tedious to handle.
Change your socialLogin function to below, your function would return a promise object which you can consume in socialPluginLogin via then which you are already doing.
socialLogin:function(data){
return $http.post($rootScope.apiURL+'sociallogin',data)
},
I realize this is a very similar question to this one. But I'm still unclear on how to do it in my situation. Just need some help with a successful callback.
This is what works:
function getStuff(accountNumber) {
var logMessage = 'POST GetStuff';
return $http.post(GetStuff, { custId: accountNumber })
.then(log);
}
function log(response) {
logger.debug(response);
return response;
}
This is what I want to accomplish:
function getStuff(accountNumber) {
var logMessage = 'POST GetStuff';
return $http.post(GetStuff, { custId: accountNumber })
.then(log(response, logMessage);
}
function log(response, logMessage) {
logger.debug(logMessage, response);
return response;
}
You can use this:
function getStuff(accountNumber) {
var logMessage = 'POST GetStuff';
return $http.post(GetStuff, { custId: accountNumber })
.then(
function success(response) {
return log(response, logMessage);
}
);
}
Depending on your preference/requirements you could do a few things. I normally write promise callbacks like this, so you could do:
.then(function success(response){
return log(response, logMessage);
});
or, depending on how you feel about this way (i know some people don't like it, i try to avoid unless absoluley nessesary)
.then(log.bind(null, response, logMessage));
Do either of these work for you?
See if it can help you:
function getStuff(accountNumber) {
var logMessage = 'POST GetStuff';
var deferred = $q.defer();
return $http.post(GetStuff, { custId: accountNumber })
.success(function(response){
deferred.resolve(response);
log(response, logMessage);
}).error(function(){
deferred.reject();
})
return deferred.promise;
}
In angular, I have this factory
.factory('Users', function($http) {
var users = [];
return {
getUsers: function() {
return $http.get("data.json")
.then(function(response) {
users = response.data;
return users;
});
},
getUser: function(id) {
for (i = 0; i < users.length; i++) {
if (users[i].id == id) {
return users[i];
}
}
return null;
}
}
})
And then load that data in my controller
.controller('SessionsCtrl', function($scope, Users) {
$scope.users = Users.getUsers();
})
If I console.log the response from the http request, I am getting the data, but for some reason, the scope data won't update.
I've seen examples where the controller would look like this
Users.getUsers().then(function(data) {
$scope.users = data;
});
but from my understanding, I shouldn't need to since $http is already returning a promise. Am I missing something? Do I need to involve $q at all?
This will work:
getUsers: function() {
return $http.get("data.json");
},
and:
Users.getUsers().then(function(data) {
$scope.users = data.data;
});
What you wrote however will not work, simply because you can't directly return a result from an operation that will complete later such as a $http call.
The problem with this:
getUsers: function() {
return $http.get("data.json")
.then(function(response) {
users = response.data;
return users;
});
},
Is that by the time the return users; line executes the ajax call is still in progress and nothing has been returned yet, so you will get nothing for users. For what you're looking to do I would go about using a callback:
getUsers: function(callback) {
$http.get("data.json")
.then(function(response) {
users = response.data;
callback(users);
});
},
Usage:
Users.getUsers(function(data) {
$scope.users = data;
});
Your getUsers function is still returning a promise because its returning the value of $http.get. So, yes, the value you're assigning to $scope.users is a promise. You'll have to handle the promise to set the value to $scope.users according to your example above:
Users.getUsers().then(function(data) {
$scope.users = data;
});
I have a REST call in service layer on which I have defined a promise which is making this asynchronous call a synchronous one and I am calling it from my controller method. Below is the code:
service method:
app.lazyload.factory('myService',['$http','$q', function($http,$q) {
return{
showAll :function ()
{
var deferred = $q.defer();
$http.post('rest/getAll?cd='+ (new Date()).getTime())
.success(function(data)
{
deferred.resolve(data);
})
.error(function(data)
{
deferred.reject(null);
console.log("in error block");
});
return deferred.promise;
}
};
}]);
controller method:
$scope.showAll = function()
{
var promise = myService.showAll();
promise.then(function success(data) {
$scope.allitems = data;
console.log(data);
console.log('$scope.allitems'+$scope.allitems[0].name);
$scope.showAllitems = true;
blockMyUI();
}, function error(msg) {
console.error(msg);
});
};
While debugging this javascript if I halt it for 2 sec i get the response but i don't get it if done non-stop. This means all REST call are working fine but there is some problem in my 'promise'. This promise is not waiting for REST call to complete which I want.
Try using $watch in controller.
var dataFromFactory = '';
myService.showAll().then( function(data){
dataFromFactory = data;
}
$scope.$watch(function () {
return dataFromFactory;
},
function (val) {
$scope.allitems = val;
console.log(val);
//the rest value you want.
}, false);