How can get value from the Promise return by $http service
>d {$$state: Object}
$$state: Object
status: 1
value: Array[1]
__proto__: Object
__proto__: Object
How to get the value in the d object
s.states = '';
$http.get('/api/random').then(function(response) {
s.states = response;
}, function(error) {
}).finally(function() {
})
console.log(s.states);
which shows the above result. $$state so how can get the value from it?
As suggested above:
promise.then(function(value) {
// Value contains the data received in the response
}, function(error) {
// This is called when error occurs.
}
)
The promise itself does not contain a value. It returns the value in the future ("promises" to return a value) when it's available. And when it becomes available (or not), one of two callbacks passed to then() methods gets triggered.
So basically, you should make calls like this:
$http.get('/api/random').then(function(response) {
// Do some stuff with response.
});
You can pass a callback to finally() method callback, which will be run regardless of success or error in promise.
$http.get('/api/random').then(function(response) {
// This one is triggered in case of successful response.
}, function(error) {
// This code runs in case of error
}).finally(function() {
// And this block will be triggered anyway after the promise returns.
});
Related
In my website, I have API's for twitter and facebook which enables the "mentions" feature (the one that pops up whenever we use the # symbol)
However, it is often that the access token for some feature is often expires resulting in the API not working. I store all my API's in an array and then I need to check if the token has failed or not resulting in resolved or rejected API promise.
This is an older code that needs changing due $q.all. As $q.all works whenever all the promises have been resolved, thus triggering the .then() call, this results in the .then() function NEVER working in my case (as the Facebook API is never working)
I need to find a condition where each API is checked and the .then() runs for only that API that is resolved (twitter in this case) and ignores the failed API (Facebook in this case)
if (selectedIds.allowed.TW) {
usersApi.push(TS.loginResource.getTwitterProfiles({
subUserId: selectedIds.allowed.TW,
name: searchTerm
}).$promise);
}
if (selectedIds.allowed.FB || selectedIds.allowed.FB_PAGE ||
selectedIds.allowed.FB_GROUP) {
$scope.post.showTags = true;
usersApi.push(TS.loginResource.getFbPages({
subUserId: selectedIds.allowed.FB_PAGE || selectedIds.allowed.FB
|| selectedIds.allowed.FB_GROUP,
name: searchTerm
}).$promise);
}
if (usersApi.length) {
$q.all(usersApi).then(function (responses) {
var tags1 = responses[0];
tags1.forEach(function (tag, i) {
tags1[i].name = tag.name.replace(/\"/g, "");
});
$scope.post.tags = tags1;
if (usersApi.length > 1) {
var tags2 = responses[1]
tags2.forEach(function (tag, i) {
tags2[i].name = tag.name.replace(/\"/g, "");
});
$scope.post.tags = $scope.post.tags.concat(tags2);
}
})
}
}, 500);
} else {
$scope.post.tags = [];
$scope.post.showTags = false;
}
I think you are looking to chain backup response that catch the api error and return a new success resolved promise on each specific api call before you wait on "all" of them.
apiCalls.push(doTwiterStuff().then(handleTwiterSuccess, handleApiFailure);
apiClass.push(doFBStuff().then(handleFbSuccess, handleApiFailure);
Promise.all(apiCalls).then(arr => {
arr.filter(x => !isNil(x)).forEach(x => doSomethingWithApiResult(x));
});
function handleApiFailure(x) {
...
return Promise.resolve(null);
}
Hopes this helps.
$q.all is not resilient1
If one of the promises is rejected, the $q.all is rejected with the first error.
To create a resilient composite promise, that is a promise that waits for all the promises to complete pass or fail, use .catch on each individual promise to convert the rejected promise to a successful promise.
var resilientPromises = [];
angular.forEach(promises, function(p) {
var resilientP = p.catch( function(result) {
//return to convert rejection to success
return result;
});
resilientPromises.push(resilientP);
});
$q.all(resilientPromises).then( function (results) {
//process results
});
The two things to take away from this answer:
A $q.all promise is not resilient. It is rejected with the first rejected promise.
A fulfilled promise can be created from a rejected promise by returning a value to the onRejected function of either the .then method or the .catch method.
I have a Api in which retrieves a custom header: X-Total-Count : "total of items", I'm using angular with ngResource.
My factory look like this:
app.factory("shopFactory", function ($resource) {
return {
User: $resource("http://localhost:58495/users/api/User/?id=:id", { id: "#id" }),
Category: $resource("http://localhost:58495/category/:id", { id: "#id" }),
Product: $resource("http://localhost:58495/products/?from=:from&to=:to", { from: "#from", to: "#to" })
};
});
And when I call it:
var productServer = shopFactory.Product.query({ from: 0, to: 10 }).$promise.then(function (response) {
$scope.product = response;
console.log(response);
}, function (error) {
console.log("ERROR");
console.log(error);
});
How can I access my custom header through ngResource, I can access it but with $http, I want to do it with the $resource way, Thanks
The query action method can be called with three arguments:
Resource.query([parameters], [success], [error])
The success callback is called with (value (Object|Array), responseHeaders (Function), status (number), statusText (string)) arguments, where the value is the populated resource instance or collection object. The error callback is called with (httpResponse) argument.
var productServer = shopFactory.Product.query(
{ from: 0, to: 10 },
function success (value, headers, status, statusText) {
$scope.product = value;
console.log(value);
console.log(headers());
},
function error (error) {
console.log("ERROR");
console.log(error);
}
);
For more information, see AngularJS $resource Service API Reference.
whats the difference between using $promise.then and the success function,
The function in the .then method exposes only the value of the final response. While the success callback exposes four arguments: value (Object|Array), responseHeaders (Function), status (number), statusText (string).
The $promise can be passed as an argument to other functions and its .then method can be invoked multiple times.
Another very important difference is that the .then method creates a new promise from values returned.
Chaining promises
Because calling the .then method of a promise returns a new derived promise, it is easily possible to create a chain of promises.
It is possible to create chains of any length and since a promise can be resolved with another promise (which will defer its resolution further), it is possible to pause/defer resolution of the promises at any point in the chain. This makes it possible to implement powerful APIs.
— AngularJS $q Service API Reference (Chaining Promises)
I thought that I had this all figured out on previous projects through the years.. Apparently not.
Goal : Take Service that calls other Services and if there is any type of error being returned ( not a status of 200 ) then I need the async thing to be waiting and not proceeding.
Seems to me like I don't ever see really that great of examples as it is all very simplistic.
I read various articles about what Angular (1) is doing under the hood , and i see that there are $q, .then, .success etc..
Seems that I am having issues with return and with other nested and bundled service calls being made without any checking of a problem.
Essentially this image shows what is coming back
data : null ( that is bad)
errorList Array1 0 "This order cannot be submitted... " ( bad too)
hasErrors : true ( bad as well)
So that data is important to me to capture and display to user and then NOT move onto more processing
This is my order of operations
this.submitEnrollment = function (enrollment) {
return getSubmit(requestData);
}
// Which CALLS below
var getSubmit = function (request) {
return SparkRequestService
.submitRequest(request)
.then(
function (resData) {
console.log("resData", resData);
enrollmentService.resetEnrollment();
return resData;
},
function (resData) {
console.log('error');
}
);
}
Then I'm certainly calling SparkRequestService.submitRequest(request)
but based on the image attached, I am getting the error in the resData
So, it seems that I need to interrogate the resData right? So then I really should NOT ALLOW this other service to be called enrollmentService.resetEnrollment();
How can i refactor to stop from that getting processed? if statement in the .then ?
To prevent a rejection handler from converting a rejected promise to a fulfilled promise it is important use a throw statement in the rejection handler:
var getSubmit = function (request) {
return SparkRequestService
.submitRequest(request)
.then(
function (resData) {
console.log("resData", resData);
enrollmentService.resetEnrollment();
return resData;
},
function (errorResponse) {
console.log('error');
//IMPORTANT
//throw to chain rejection
throw errorResponse;
}
);
}
When a function omits a return or throw statement, the function returns a value of undefined. This will convert a rejected promise to a fulfilled promise that resolves with a value of undefined.
Problem is that ... it is a business error wrapped up in a return object
To convert a fulfilled promise to a rejected promise, use a throw statement.
this.submitEnrollment = function (enrollment) {
var promise = getSubmit(requestData);
var newPromise = promise.then(function(response) {
if (response.data.hasErrors) {
console.log(response.data.errorList);
response.data.errorList.push("submitEnrollent: Rejected");
//THROW to create rejection
throw response;
} else {
//RETURN response to chain success
return response;
}
});
return newPromise;
}
When a promise is converted to a rejection, all subsequent success handlers in the chain will be skipped. The chain will be followed until a rejection handler is found.
it seems that the promise returned by SparkRequestService.submitRequest(request) is not rejected when you get the error inside resData. For this reason the successCallback of then is invoked and not the second one, the errorCallback.
For this reason, inside the successCallback you need to inspect the data of resData to check errors and behave accordingly, for example:
var getSubmit = function (request) {
return SparkRequestService
.submitRequest(request)
.then(function (resData) {
console.log("resData", resData);
if(resData === null) { // Check for errors
// There is an error, manage it inside this block of code
// ...
// You can also create a rejected promise with $q.reject() and passing resData containing the errors
return $q.reject(resData);
} else {
// Call resetEnrollment() in the ELSE branch so, it is executed only if resData does not contain errors
enrollmentService.resetEnrollment();
return resData;
}
},
function (resData) {
console.log('error');
}
);
};
When should I use then() method and what is the difference between then(), success(), error() methods ?
Other than the success un-wraps the response into four properties in callback, where as then does not. There is subtle difference between the two.
The then function returns a promise that is resolved by the return values for it's success and error callbacks.
The success and error too return a promise but it is always resolved with the return data of $http call itself. This is how the implementation for success in angular source looks like:
promise.success = function(fn) {
promise.then(function(response) {
fn(response.data, response.status, response.headers, config);
});
return promise;
};
To understand how it can affect our implementation, consider an example where we retrieve whether user exists based on email id. The http implementation below tries to retrieve the user based on userid.
$scope.userExists= $http.get('/users?email='test#abc.com'')
.then(function(response) {
if(response.data) return true; //data is the data returned from server
else return false;
});
The promise assigned to userExists resolves to either true or false;
Whereas if we use success
$scope.userExists= $http.get('/users?email='test#abc.com'')
.success(function(data) { //data is the response user data from server.
if(data) return true; // These statements have no affect.
else return false;
});
The promise assigned to userExists resolves either a user object or null, because success returns the original $http.get promise.
Bottom line is use then if you want to do some type of promise chaining.
then() method fires in both the success and failure cases. The then() method takes two arguments a success and an error callback which will be called with a response object.
I have a service that returns a promise. I would like to check if the value returned is an empty object. How can I achieve this. I guess I need to extract the returned value from the promise object somehow.
Here's my resource:
app.factory('Auth', ['$resource',
function($resource) {
return $resource('/user/identify', {}, {
identify: {
url: '/user/identify'
},
});
}
]);
Then in a service:
Auth.identify(function(data) {
// This always passes since data contains promise propeties
if (!_.isEmpty(data)) {
}
});
A console log of data gives:
Resource
$promise: Object
$resolved: true
__proto__: Resource
I can check for expected properties when the object is not empty but would like a more generic method.
To unwrap the return value you can access the promise directly:
Auth.identify()
.$promise
.then(function(data) {
if (!_.isEmpty(data)) {
// ...
}
});
You're so close. You shouldn't call the response "data" when it is in fact a Resource object, which looks a lot like the Resource object you posted:
$resource('/api/...').get({...}).then(function(response) {
if (response.data) {
// the response has a data field!
}
}
// note: this is using query(), which expects an array
$resource('/api/...').query({...}).then(function(response) {
if (response.length > 0) {
// the response data is embedded in the response array
}
});