i've a function that return a boolean according to http.get call.
function checkValue (value) {
var defer = $q.defer();
var request = $http({
method: "get",
url: "someurl"
});
request.success(function (data) {
defer.resolve(data.response);
});
return defer.promise;
}
The problem is that return value is an object like this:
d {$$state: Object}
$$state: Object
status: 1
value: true
__proto__: Object
__proto__: d
How could i resolve it?
Yes, your function is returning a Promise object. The $$state property belongs to the promise object and is used by Angular internally (as suggested by $$ prefix) and therefore not to be used by developers using Angular. More interesting is that promise object has a "then" method which can be used to attach handlers that are called when the promise gets resolved. Promise gets resolved when the defer object related to the promise is resolved.
So, you could use your code as
checkValue.then(function (data) {
// This is called when the XHR response comes in and
// defer.resolve() is called in the checkValue function.
});
But, there is a better approach to this. Using promise chaining.
Which essentially removes the need to create a new defer object.
function checkValue (value) {
return $http({
method: "get",
url: "someurl"
}).then(function (data) {
return data.response;
});
}
Explaining everything about how Promises work is may be too much for this post. There are already awesome works done on that.
But, basically, $http already returns a promise. So you can just use this promise instead of creating a new one. The end usage of the function remains exactly the same as the snippet above.
BTW, .success() handlers are deprecated. So better start using .then() on your apps already.
Since you are using Promise, you need to use .then callback in order to get response or error:
function checkValue (value) {
var defer = $q.defer();
var request = $http({
method: "get",
url: "someurl"
});
request.success(function (data) {
defer.resolve(data.response);
});
return defer.promise;
}
var promise = checkValue('Hello World');
promise.then(function(response) {
//success
console.log(response);
}, function(reason) {
//failed
console.log(reason);
});
then(successCallback, errorCallback, notifyCallback) – regardless of
when the promise was or will be resolved or rejected, then calls one
of the success or error callbacks asynchronously as soon as the result
is available. The callbacks are called with a single argument: the
result or rejection reason. Additionally, the notify callback may be
called zero or more times to provide a progress indication, before the
promise is resolved or rejected.
But the optimized approach would be using $http's inbuilt promise instead of creating a new one.
var request = $http({
method: 'GET',
url: '/someUrl'
});
request.then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
You should try this,
function checkValue (value) {
return $q(resolve, reject) {
$http({
method: "get",
url: "someurl"
}).success(function (data) {
resolve(data.response);
}).then (function (error) {
reject(error);
});
}
}
This will resolve your data
Related
I am chaining two calls to a function that uses fetch and returns a promise.
The calls sometimes arrive in the wrong order, reversed.
I assume my function code is wrong, derived from a bad understanding of either promises, fetch, or both.
This is the function code, simplified:
function shop(id) {
return new Promise(function(resolve, reject) {
fetch('/shop', {
method: 'post',
body: JSON.stringify({id: id}) ,
headers: {'Content-type': 'application/json '}
}).then(function (response) {
return response.json();
}).then(function (data) {
console.log(data);
resolve(data);
})
})
}
I chain the function in this manner:
shop('potatoe')
.then(shop('mushrooms'));
As explained, these two sometimes arrive in the wrong order, with mushrooms being shopped before potatoes.
May I have my returns or resolve() wrongly written in the shop() function?
Thank you for your help.
The main issue is that you call shop('mushrooms') immediately, synchronously. You didn't pass a callback to the then method, but instead executed what would be the intended callback. So change the main code to:
shop('potatoe')
.then(() => shop('mushrooms'));
This solves your problem.
However, you are creating a useless promise in your function. The fetch().then().then() chain already returns a promise; you don't need to create yet another one. Read about the promise constructor antipattern.
So remove this new Promise wrapper, and remove the final .then() call which was only there to call resolve:
function shop(id) {
// return the promise returned by this promise chain:
return fetch('/shop', {
method: 'post',
body: JSON.stringify({id: id}) ,
headers: {'Content-type': 'application/json '}
}).then(function (response) {
return response.json();
});
}
This question already has answers here:
What is the explicit promise construction antipattern and how do I avoid it?
(3 answers)
Closed 3 years ago.
There is a funcion returning a promise:
req.postP = function () {
var $promise = $.ajax({
url: self._url(url),
type: "POST",
data: JSON.stringify(data),
headers: headers,
contentType: self.JSON_CONTENT_TYPE,
dataType: "json"
});
return new Promise( (resolve, reject) => {
return $promise.then(resolve, reject);
} );
}
And another function that calls the first function:
req
.postP(POST_REGISTER, userData)
.then((data) => {
// is never ecexuted
})
.catch((err) => {
console.log(typeof err.then === "function"); // true
});
The then() function is never executed.
It seems that the promise is inside the catch function as err since err.then is a function.
The req.postP() function is called by other function as well and works in those cases.
The casting to a standard promise, was not the problem.
The problem was the dataType. According to the jQuery docs:
The type of data that you're expecting back from the server.
Since the server does not return any data for this request on success - but jQuery expected data - the promise was always rejected.
Related:
jQuery returning "parsererror" for ajax request
I am pretty new to AngularJS and Javascript. I am creating a app in which I am planning to use one function to do all ajax related operation(factory in angularjs).
This function will be only one gateway for all ajax operations. When I return promise as a success it works properly. but returning error promise do not work.
Here is a sample code. I am expecting return of promise in error function if promise fails but it goes to success
var myApp = angular.module('myApp', []);
myApp.controller('FirstController, function($scope, util){
util.doAjax().then(function(response){
// This function is called in both success and error
}, function(err){
// This is never called why ?
});
});
myApp.factory('util, function($http){
return $http({
method: 'GET',
url: 'http://www.example.com'
}).then(function(response){
// This will return success promise
return response;
}, function(err){
// This should return error promise
return err;
});
});
Currently you are directly returning a data from error function, which is chaining the promise and calling it underlying .then method.
While returning an error you have to reject a promise by creating a new custom promise using $q
return $q.reject(err)
Other important thing is, you should create method in a service with name
myApp.factory('util', function($http, $q){
//Exposed method
return {
doAjax : function() {
return $http({
method: 'GET',
url: 'http://www.example.com'
}).then(function(response){
// This will return success promise
return response.data; // returned data
}, function(err){
// return error promise with err object
return $q.reject(err);
});
}
}
});
This way you are not returning a promise.
You must return the $http promise instead like so:
myApp.factory('util', function($http){
return {
ajax: function () {
var httpPromise = $http({
method: 'GET',
url: 'http://www.example.com'
});
httpPromise.then(function(response){
// This will return success promise
// return response;
}, function(err){
// This should return error promise
// return err;
});
return httpPromise;
};
});
And also, return inside promise resolutions are not needed, you can use it for loggin and stuff but it doesn't require a return value because it is the resolution it self.
I am trying to reject a deferred object within a $http.get call but it is not being properly rejected. The errorcallback is not being called, and I just can't figure out why.
Here is basically what I have:
var promise = this.SomeAsyncCall(this.$.SomeID)
.then(
function ()
{
service.SendAsyncDownloadReqeuest(someOtherID);
},
this.ErrorHandler.HandleError)
.then(this._DownloadInitiated, this.ErrorHandler.HandleError);
promise["finally"](this._DownloadRequestFinished);
And here is the service.SendAsyncDownloadRequest:
var SendAsyncDownloadReqeuest = function (ID)
{
var url = "someUrl?ID=" + customerID;
var navigator = self.$window.navigator;
var window = self.$window;
var deferred = self.$q.defer();
self.$http.get(url, { responseType: 'arraybuffer' })
.success( function(data, status, headers) {
var success = false;
//Initiate download via blob. Set success
success ? deferred.resolve() : deferred.reject();
})
.error(function (data, status)
{
var error =
{
//Some error properties
}
deferred.reject(error);
});
return deferred.promise;
};
When I test this by returning a 500 status code from the server, it reaches the .error block of the http get call and completes the reject line, but the ErrorHandler's HandleError method is not reached. The HandleError method is correct since it works with errorcallbacks for promises rejected in anything that's not $http.get.
You're never passing the promise from service.SendAsyncDownloadReqeuest(someOtherID); back to your HandleError function. You need to change your code to this:
var promise = this.SomeAsyncCall(this.$.SomeID)
.then(
function ()
{
return service.SendAsyncDownloadReqeuest(someOtherID);
},
this.ErrorHandler.HandleError)
.then(this._DownloadInitiated, this.ErrorHandler.HandleError);
promise["finally"](this._DownloadRequestFinished);
If you want to be a little clearer you could change it to this:
var promise = this.SomeAsyncCall(this.$.SomeID)
.then(function () {
service.SendAsyncDownloadReqeuest(someOtherID).then(
this._DownloadInitiated,
this.ErrorHandler.HandleError);
},
this.ErrorHandler.HandleError);
promise["finally"](this._DownloadRequestFinished);
Don't use the success method either way.Both methods have been deprecated.
The $http legacy promise methods success and error have been
deprecated. Use the standard then method instead. If
$httpProvider.useLegacyPromiseExtensions is set to false then these
methods will throw $http/legacy error.
Here is the shortcut method
$http.post('/someUrl', data, config).then(successCallback, errorCallback);
Here is a longer GET method sample
$http({
method: 'GET',
url: '/someUrl'
}).then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
Official Documentation
I am trying to work through JS Promises in node.js and don't get the solution for passing promises between different function.
The task
For a main logic, I need to get a json object of items from a REST API. The API handling itself is located in a api.js file.
The request to the API inthere is made through the request-promise module. I have a private makeRequest function and public helper functions, like API.getItems().
The main logic in index.js needs to wait for the API function until it can be executed.
Questions
The promise passing kind of works, but I am not sure if this is more than a coincidence. Is it correct to return a Promise which returns the responses in makeRequest?
Do I really need all the promises to make the main logic work only after waiting for the items to be setup? Is there a simpler way?
I still need to figure out, how to best handle errors from a) the makeRequest and b) the getItems functions. What's the best practice with Promises therefor? Passing Error objects?
Here is the Code that I came up with right now:
// index.js
var API = require('./lib/api');
var items;
function mainLogic() {
if (items instanceof Error) {
console.log("No items present. Stopping main logic.");
return;
}
// ... do something with items
}
API.getItems().then(function (response) {
if (response) {
console.log(response);
items = response;
mainLogic();
}
}, function (err) {
console.log(err);
});
api.js
// ./lib/api.js
var request = require('request-promise');
// constructor
var API = function () {
var api = this;
api.endpoint = "https://api.example.com/v1";
//...
};
API.prototype.getItems = function () {
var api = this;
var endpoint = '/items';
return new Promise(function (resolve, reject) {
var request = makeRequest(api, endpoint).then(function (response) {
if (200 === response.statusCode) {
resolve(response.body.items);
}
}, function (err) {
reject(false);
});
});
};
function makeRequest(api, endpoint) {
var url = api.endpoint + endpoint;
var options = {
method: 'GET',
uri: url,
body: {},
headers: {},
simple: false,
resolveWithFullResponse: true,
json: true
};
return request(options)
.then(function (response) {
console.log(response.body);
return response;
})
.catch(function (err) {
return Error(err);
});
}
module.exports = new API();
Some more background:
At first I started to make API request with the request module, that works with callbacks. Since these were called async, the items never made it to the main logic and I used to handle it with Promises.
You are missing two things here:
That you can chain promises directly and
the way promise error handling works.
You can change the return statement in makeRequest() to:
return request(options);
Since makeRequest() returns a promise, you can reuse it in getItems() and you don't have to create a new promise explicitly. The .then() function already does this for you:
return makeRequest(api, endpoint)
.then(function (response) {
if (200 === response.statusCode) {
return response.body.items;
}
else {
// throw an exception or call Promise.reject() with a proper error
}
});
If the promise returned by makeRequest() was rejected and you don't handle rejection -- like in the above code --, the promise returned by .then() will also be rejected. You can compare the behaviour to exceptions. If you don't catch one, it bubbles up the callstack.
Finally, in index.js you should use getItems() like this:
API.getItems().then(function (response) {
// Here you are sure that everything worked. No additional checks required.
// Whatever you want to do with the response, do it here.
// Don't assign response to another variable outside of this scope.
// If processing the response is complex, rather pass it to another
// function directly.
}, function (err) {
// handle the error
});
I recommend this blog post to better understand the concept of promises:
https://blog.domenic.me/youre-missing-the-point-of-promises/