Reference error while trying make call to different end points - javascript

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'});
};

Related

Need to call Two APIs In Loop using node js

I have an array of ssn number and I have two api list in which I need to pass ssn number as request json so I need to call both api inside ssn loop so I pass ssn to json request during call both api but code is not work properly both api call at a time simulteniously, Where I need to call both api one by one.
Both API details and code are as follow
My Code:
let ssn = [460458524, 637625452, 453311896, 635285187, 455791630, 642348377, 463590491, 450730278, 641201851, 379965491];
async function getCRCDetails() {
ssn.forEach(function (item) {
if(item){
let CBCOptions = {
'method': 'POST',
'url': 'https://loanboard.houstondirectauto.com/api/Report',
'headers': {
'Content-Type': 'application/json',
'Cookie': 'ci_session=udmojmlc5tfl3epbrmtvgu6nao2f031p'
},
body: JSON.stringify({
"token": loantoken,
"action": "CBCReport",
"variables": {
ssn: item
}
})
}
request(CBCOptions, function (error, response) {
console.log(item);
console.log("CBCOPtion ", CBCOptions);
if (error) throw new Error(error);
result = (JSON.parse(response.body));
console.log("Result =", result);
CRCReport.push(result);
})
let EmployerInfoOptions = {
'method': 'POST',
'url': 'https://loanboard.houstondirectauto.com/api/Report',
'headers': {
'Content-Type': 'application/json',
'Cookie': 'ci_session=udmojmlc5tfl3epbrmtvgu6nao2f031p'
},
body: JSON.stringify({
"token": loantoken,
"action": "getEmployerInfo",
"variables": {
ssn: item
}
})
}
request(EmployerInfoOptions, function (error, response) {
console.log(response.body);
})
}
Here I need to call API request one by one.Anyone Guide me please.
I prefer use async await method for this situation
you need install and require async and request-promise
after that :
const request = require("request-promise");
const async = require("async");
let ssn = [460458524, 637625452, 453311896, 635285187, 455791630, 642348377, 463590491, 450730278, 641201851, 379965491];
async function getCRCDetails() {
//like a forEache
async.eachSeries(ssn, async (item) => {
let CBCOptions = {
method: "POST",
url: "https://loanboard.houstondirectauto.com/api/Report",
headers: {
"Content-Type": "application/json",
Cookie: "ci_session=udmojmlc5tfl3epbrmtvgu6nao2f031p",
},
body: JSON.stringify({
token: loantoken,
action: "CBCReport",
variables: {
ssn: item,
},
}),
};
let EmployerInfoOptions = {
method: "POST",
url: "https://loanboard.houstondirectauto.com/api/Report",
headers: {
"Content-Type": "application/json",
Cookie: "ci_session=udmojmlc5tfl3epbrmtvgu6nao2f031p",
},
body: JSON.stringify({
token: loantoken,
action: "getEmployerInfo",
variables: {
ssn: item,
},
}),
};
try {
let resultCBCOptions = await request(CBCOptions);
let EmployerInfoOptions = await request(EmployerInfoOptions);
console.log(resultCBCOptions)
console.log(EmployerInfoOptions)
//do pushing resultCBCOptions
//do pushing EmployerInfoOptions
} catch (error) {
console.log(error);
}
},
() => {
console.log("finished");
}
);
}
In Node the request methods that you are using are asynchronous. Meaning the runner (server) that runs the code does not wait for the request to finish and just continues to execute the next lines.
One thing that you can do is,
request.post(params).on("response", function(response) {
//....Do stuff with your data you recieve
// Make the next call here
request.post(params).on("response"), function() {
// Here you will have the second call's results
}
})
This ensures that both the API calls happen in order and only after the first one finishes.
Note:
The request library that you are using has been deprecated back in 2020. See https://github.com/request/request Hence, I would suggest you use other libraries like the standard https or http library that is shipped with node or you can use axios.
If you use a forEach loop without awaiting the results, you'll execute them all at the same time. Moreover, request library is kind of old and you need to convert its functions to return a promise.
Here's how I would do it.
const ssn = [1,2,3,4];
function download(item) {
return new Promise(function(resolve, reject) {
let options = {}; // construct your request
request(options, function (error, response) {
if(error) {
return reject(error);
}
resolve(response);
})
}
}
ssn = ssn.map(async function(item) {
let res = await download(item);
// process the result
return res;
});
You can also use the Bluebird library or get another client library such as got or axios.

Promise Chaining is not working as expected

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;
})

Axios - Cant set and get data in object

I am using the Axios library for my ajax requests so I created an instance of axios.
When I hit the endpoint /user/login, the success response will return me a token that I will use in the header for future calls as the API is secured.
The problem is when I do a console.log(authUser) the object is empty even though in the .then(), I am setting authUser.bearerToken.
Why is this happening? And what's the solution? Thanks. See code below.
var ax = axios.create({
baseURL: 'http://api.site.test',
timeout: 5000,
headers: {
'X-Api-Client-Secret': 'xxxxxxxxxxxxxxxx'
}
});
var authUser = {};
// log the user in
ax.post('/user/login', {
email: 'e#maiiiiiiiiil.com',
password: 'ThisIsACoolPassword123!'
})
.then(function (response) {
// set the bearer token
authUser.bearerToken = response.data.token;
ax.defaults.headers.common['Authorization'] = authUser.bearerToken;
})
.catch(function (error) {
console.log(error);
});
console.log(authUser);
It's because its async. The code that talks to /user/login takes some time but your code continues.
So the order is
Create base axios
Define authUser as empty object
Send a request to /user/login
Console.log authUser
Get the response from the post request
You can see it more clearly if you put 3 console logs.
var ax = axios.create({
baseURL: 'http://api.site.test',
timeout: 5000,
headers: {
'X-Api-Client-Secret': 'xxxxxxxxxxxxxxxx'
}
});
var authUser = {};
console.log('authUser is ' + authUser);
// log the user in
ax.post('/user/login', {
email: 'e#maiiiiiiiiil.com',
password: 'ThisIsACoolPassword123!'
})
.then(function (response) {
// set the bearer token
authUser.bearerToken = response.data.token;
ax.defaults.headers.common['Authorization'] = authUser.bearerToken;
console.log('2. authUser is ' + authUser);
})
.catch(function (error) {
console.log(error);
});
console.log('3. authUser is ' + authUser);
You will see it in the following order: 1, 3, 2 and not 1, 2, 3.
ax.post is asynchronous ( non blocking ) so it won't execute in the order you want it to execute i.e it can execute any time ( or concurrently ). you either have to use callbacks or async...await to handle this
function f() {
var ax = axios.create({
baseURL: 'http://api.site.test',
timeout: 5000,
headers: {
'X-Api-Client-Secret': 'xxxxxxxxxxxxxxxx'
}
});
var authUser = {};
var response;
; ( async () => {
// log the user in
try {
response = await ax.post('/user/login', {
email: 'e#maiiiiiiiiil.com',
password: 'ThisIsACoolPassword123!'
})
} catch(ex) {
response = ex;
} finally {
if ( Error[Symbol.hasInstance](response) )
return console.log(response);
authUser.bearerToken = response.data.token;
ax.defaults.headers.common['Authorization'] = authUser.bearerToken;
}
})();
console.log(authUser)
}

AngularJS Get Status error details $http

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');
})

How to design services to fetch data that are required to be called multiple times?

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.

Categories