I am trying use the promise chaining for the $http.get calls I am making from my angular application
$http.get(url, config)
.then(newViewRequest)
.then(function (response) { // success async
$scope.viewRequest1.data = response.data;
}
And in my newViewRequest I making a new call to other end point and I need to only send the response back if the call with in the newViewRequest is successful. Below is what I am trying
var newViewRequest = function (response) {
var url1 = $rootScope.BaseURL;
var config = {
headers: {
'Authorization': `Basic ${$scope.key}`,
'Prefer': 'odata.maxpagesize=2000'
}
};
var newresponse = $http.get(url1, config);
if (newresponse.status = 200)
return newresponse;
else return response;
};
But it always send the request response with out validating the status or anything. How can I approach this.
The $http.get in newViewRequest returns a Promise. You need to wait for it to resolve to get get the status. And you have to return the Promise from newViewRequest to do proper chaining.
return $http.get(url1, config)
.then(newresponse => {
if (newresponse.status = 200)
return newresponse;
else return response;
})
.catch(err => {
return response;
})
Related
I have never used fetch before, and have followed the documentation, however, no results are being returned from my backend. When I submit the form, the url changes, and all appears fine in my console, but no response from my express backend.
The following code is what I have after my form in a script tag. Can someone please advise?
async function getSample(url = `http://localhost:3000/lookup/${url}`, data = {}) {
const response = await fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
return response.json();
}
document.getElementById('search').addEventListener('submit', function(e) {
event.respondWith(
new Response(myBody, {
headers: {'Content-Type': 'application/json'}
})
);
});
You could try creating a promise and then handling the value returned by the fetch with resolve and reject
async function getSample(url = `http://localhost:3000/lookup/${url}`, data = {}){
return new Promise(function (resolve, reject) {
fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
}).then(async response => {
if (response.ok) {
response.json().then(json => resolve(json));
} else {
response.json().then(json => reject(json));
};
}).catch(async error => {
reject(error);
});
});
};
You would then call it like
getSample(...)
.then(results => {
//Code when fetch is successful
}.catch(error => {
//Code when fetch fails
};
I think the problem with it returning nothing is that getSample is an async function, but I imagine you're calling it within a program that isn't async, and so whatever code comes after getSample is using trying to use the value returned from getSample, but nothing's been returned yet, so it's using an empty value. Either that or the return of getSample is happening before the fetch completes. I'm not sure of the exact order that things happen, but a promise should fix your problem
I am trying to call a odata end Point and check the response and make a another call to different endpoint if the condition is not met. If I don’t have the condition and making just one call to just one end point it works, but below code is throwing Reference error even with the attempt to the first call
$scope.getRequest = function () {
var url = $rootScope.BaseURL;
var config = {
headers: {
'Authorization': `Basic ${$scope.key}`,
'Prefer': 'odata.maxpagesize=2000'
}
};
$http.get(url, config)
.then(
function (response) { // success async
$scope.viewRequest.data = response.data;
},
function (response) { // failure async
console.log("There was an error getting the request from CORE");
}
);
if (viewRequest.data.REV_SAMPLE_CMQREQUEST.length = 0) {
var url = $rootScope.BaseURL + `CMQ_REQUEST('${$scope.viewRequest.barcode}’)`;
var config = {
headers: {
'Authorization': `Basic ${$scope.key}`,
'Prefer': 'odata.maxpagesize=2000'
}
};
$http.get(url, config)
.then(
function (response1) { // success async
$scope.viewRequest1.data = response1.data;
},
function (response1) { // failure async
console.log("There was an error getting the request from CORE");
}
);
}
};
Below is the screenshot of the error
$scope.getRequest = function () {
var url = $rootScope.BaseURL;
var config = {
headers: {
'Authorization': `Basic ${$scope.key}`,
'Prefer': 'odata.maxpagesize=2000'
}
};
$http.get(url, config)
.then(function (response) { // success async
$scope.viewRequest.data = response.data;
},
function (response) { // failure async
console.log("There was an error getting the request from CORE");
}
)
.then(nextViewRequest);
};
var newViewRequest = function (response) {
var url1 = $rootScope.BaseURL + `CMQ_REQUEST('${$scope.viewRequest.barcode}')`;
if ($scope.viewRequest.data.REV_SAMPLE_CMQREQUEST.length = 0) {
return $http.get(url1, config)
.then(
function (response1) { // success async
$scope.viewRequest1.data = response1.data;
},
function (response1) { // failure async
console.log("There was an error getting the request from CORE");
}
);
}
return $q.reject({ message: 'Validations didnt work' });
};
You are making 2 request in parallel rather than wait for the first one to finish and then make the second one, also the code is hard to read. My guess is that the second response is not returning anything because the first condition is not met.
I recommend you to read about promises chaining and the $q service to make custom rejections or resolve promises in your scenarios to order this logic your code should like something like this:
$scope.getRequest = function () {
// setup url and config
$http.get(url, config)
.then(nextViewRequest) // the return of this function will override the next result of the next promise chaining
.then(function(response) {
$scope.viewRequest1.data = response.data;
});
};
var nextViewRequest= function(response) {
// validations necessary
if(valid) {
return $http.get(url, config);
}
// If conditions are not met, then you can use the $q service to create a rejection
return $q.reject({message: 'validations on second request failed'});
};
I import the function getWeather from another .js file I've written. The result is a json blob. I've verified that I get the JSON blob back, but when I try to call the getWeather function and use .then to wait for a response and set my state I get a TypeError.
getWeather(parseFloat(lat),parseFloat(long)).then((data) =>{
this.setState({weatherType: data.currently.icon, temp: data.currently.temperature})
return data
}).catch((error) => {
console.log(error.message);
})
The getWeather function is here:
export function getWeather(lat,long) {
const params = {
headers: {
"content-type": "application/json; charset=UTF-8",
"Access-Control-Allow-Origin": "*"
},
method: "GET"
};
fetch(`https://api.com/mykey/${lat},${long}`, params)
.then(function (data) {
return data.json();
})
.then(res => {
console.log(res);
})
.catch(error => {
console.log(error);
});
}
You need to return fetch() in order to make the promise accessible from another function. Also, I would probably handle logging and errors in the calling function as when you log the data you are no longer returning it.
export function getWeather(lat,long) {
const params = {
headers: {
"content-type": "application/json; charset=UTF-8",
"Access-Control-Allow-Origin": "*"
},
method: "GET"
};
return fetch(`https://api.com/mykey/${lat},${long}`, params)
.then(function (data) {
if (!data.ok) { return new Error('custom error message here') }
return data.json();
});
}
You are most probably return that blob from the getWeather function without creating a Promise.
Try something like this:
function getWeather() {
// create blob as usual
return Promise.resolve(blob);
}
or if you already inside a then you must just retrun something from it:
fetch(`https://api.com/mykey/${lat},${long}`, params)
.then(function (data) {
return data.json();
})
.then(res => {
console.log(res);
retrun res; // return something
})
.catch(error => {
console.log(error);
});
}
I'm new angularJS student, and i want to get detail error's when i send a POST to WebApi.
I want to get Status 500 and Status 404, and make condition to show a feedback instead of the status error.
I have tried use "Intercepting HTTP calls with AngularJS", but everytime it returns 'Status -1'
Can anyone help me please?
Thanks!
#EDIT
.factory('ajaxFn', function ($http, $cookies, $location, $q) {
var post = function (url, objeto, data, successFn, errorFn) {
user = $cookies.get(btoa('user'));
pass = $cookies.get(btoa('pass'));
authHeader.Authorization = 'Basic ' + btoa(user + ':' + pass);
$http({
method: 'POST',
url: "//localhost:61115/api/main/" + CompleteUrl,
headers: authHeader,
params: objeto,
data: data
})
.then(function (result) {
successFn(result.data);
}, function (data) {
errorFn();
});
}
return {
post: post
};
})
And that is the intercepting code that i have tried
// Intercepting HTTP calls with AngularJS.
.config(function ($provide, $httpProvider) {
// Intercept http calls.
$provide.factory('MyHttpInterceptor', function ($q) {
return {
// On request success
request: function (config) {
// console.log(config); // Contains the data about the request before it is sent.
// Return the config or wrap it in a promise if blank.
return config || $q.when(config);
},
// On request failure
requestError: function (rejection) {
// console.log(rejection); // Contains the data about the error on the request.
// Return the promise rejection.
return $q.reject(rejection);
},
// On response success
response: function (response) {
// console.log(response); // Contains the data from the response.
// Return the response or promise.
return response || $q.when(response);
},
// On response failture
responseError: function (rejection) {
// console.log(rejection); // Contains the data about the error.
// Return the promise rejection.
return $q.reject(rejection);
}
};
});
// Add the interceptor to the $httpProvider.
$httpProvider.interceptors.push('MyHttpInterceptor');
})
I have a service that returns a promise.
function GetSuggestedPeersService($http, SITE_CONFIG) {
var getSuggestedPeersService = this;
var data;
getSuggestedPeersService.getSuggestedPeersList = function() {
var baseUrl = SITE_CONFIG.baseUrl + "fetchSuggestedPeers";
var response = $http({
method : 'POST',
url : baseUrl,
headers : {
'Content-Type' : 'application/x-www-form-urlencoded'
},
data : data
});
return response;
}
getSuggestedPeersService.setSuggestedPeers = function(suggestedPeers) {
getSuggestedPeersService.suggestedPeers = suggestedPeers;
}
getSuggestedPeersService.getSuggestedPeers = function() {
return getSuggestedPeersService.suggestedPeers;
}
}
Now I use the following in the Controller to resolve the promise:
//gets the suggested peers
var promiseSuggestedPeers = GetSuggestedPeersService.getSuggestedPeersList();
promiseSuggestedPeers.then(function (response) {
peerHealthController.GetSuggPeersShow = response.data;
GetSuggestedPeersService.setSuggestedPeers(peerHealthController.GetSuggPeersShow);
return peerHealthController.GetSuggPeersShow;
})
.catch(function (error) {
console.log("Something went terribly wrong Suggested Peers.");
});
Now my question is call this service multiple times and need to update this on other service calls as well.
What is the best way to write the controller part so as not to repeat the resolve promise every time I call the service?
It's been long time.
But I just wanted to answer this question.
The best way to design this would be to use a factory. So this will become a reusable service.
An example code can be the following:
var httpMethods = peerHealthApp.factory('HttpService',HttpService);
httpMethods.$inject = ['$http', 'SITE_CONFIG'];
function HttpService($http, SITE_CONFIG){
console.log("SITE_CONFIG from Peer Service: " + SITE_CONFIG);
var factory = {
httpGet : function(relativePath,data){
var baseUrl = SITE_CONFIG.baseUrl + relativePath;
var response = $http({
method : 'GET',
url : baseUrl,
headers : {
'Content-Type' : 'application/x-www-form-urlencoded'
},
data : data
});
return response;
},
httpPost : function(relativePath, data){
var baseUrl = SITE_CONFIG.baseUrl + relativePath;
var response = $http({
method : 'POST',
url : baseUrl,
headers : {
'Content-Type' : 'application/x-www-form-urlencoded'
},
data : data
});
return response;
}
};
return factory;
}
And the above can be used again and again like the following:
var data=$.param({
"url":moderatedArticleLink
});
var promiseURLMetaData = HttpService.httpPost("parseUrlMetadata", data);
promiseURLMetaData.then(function (response) {
var urlMetaData = response.data;
return urlMetaData;
})
.catch(function (error) {
console.log("Something went terribly wrong while trying to get URL Meta Data.");
});
What is the best way to write the controller part so as not to repeat the resolve promise every time I call the service?
Instead of saving the data in a service, I recommend saving the promise:
if ( !Service.get() ) {
var promise = Service.fetch();
Service.set(promise);
});
Service.get().then(function (response) {
$scope.data = response.data;
}).catch( function(errorResponse) {
console.log(errorResponse.status);
throw errorResponse;
});
By checking for the promise and only fetching if necessary, multiple controllers can share the data without caring about the order of controller instantiation. This avoids race conditions and multiple XHRs to the same resource.