http toPromise return an object - javascript

I have the function below:
getUser(userId: string) : Observable<any> {
var getUserURL = `/api/users/${userId}`,
getUserStatus = this.getUserStatus();
return this.http.get<any>(getUserURL).pipe(
catchError(this.handleError('getUser - Get User failed', null))
);
}
This returns the data from response from REST API for this URL /api/users/${userId} to toPromise
Is there any way that I can return the object that include the response data from REST API + local data(getUserStatus) which is Boolean in this case.
Thanks

Your request is not returning a Promise unless it isn't included in your example. You have an Observable.
Assuming I understand your question correctly. If you want to return the HTTP response + the local status you would do something like this using piped operators:
Service
getUser(userId: string) : Observable<any> {
const path = `/api/users/${userId}`
const userStatus = this.getUserStatus();
return this.http.get<any>(path)
.pipe(
map((response: any) => {
return { response, userStatus };
}),
catchError(this.handleError('[USER]::getUser Failed', null))
);
}
Component
this.getUser(1000).subscribe(({response, userStatus}) => {
// Handle response and status
console.log('RESPONSE', response);
console.log('USER_STATUS', userStatus);
});

Like #mtputlz said you're returning an Observable. If you want to return your reponse which is in your case a boolean. Then we can convert the obserable to a promise:
async getUser(userId: string) : any {
var getUserURL = `/api/users/${userId}`,
getUserStatus = this.getUserStatus();
return await this.http.get<any>(getUserURL).pipe(
catchError(this.handleError('getUser - Get User failed', null))
).toPromise();
}

Related

Async Javascript function is returning undefined in NodeJS

I am trying to call a function which gets data from an API and after comaprison of received data with input it should return 0 or 1 which i may include in my code but the function is returning undefined. Can;t seem to get my head in the right place.
async function cloudVerify(y, x) {
const url = `https://**myAPI**.execute-api.us-west-2.amazonaws.com/items/${y}`;
console.log(url);
await axios
.get(url)
.then((res) => {
const headerDate =
res.headers && res.headers.date ? res.headers.date : "no response date";
console.log("Status Code:", res.status);
console.log("Date in Response header:", headerDate);
const receivedData = res.data;
const receivedItem = receivedData.Item;
// console.log(receivedItem);
console.log(
`Got user with id: ${receivedItem.id}, hash: ${receivedItem.hash}`
);
console.log(`received item hash is ${receivedItem.hash}`);
console.log(`meta is : ${x}, hash: ${receivedItem.hash}`);
return 1;
})
.catch((err) => {
console.log("Error: ", err.message);
});
}
I am returning 1 but instead it gives me undefined.
When you return 1 inside the "then" method you will not return it from the cloudVerify function. You need to type return before "await axios" as well.
I think it's a scoping issue. the "return 1" is returned by your call to axios within cloudVerify, it's not the return value of that function.
Also, you might be mixing async/await with .then() - you might be able to drop the async/await and simply return the call to axios. kind of like this:
callingAxios = () => {
axios.get().then()
return 1
}
cloudVerify = (url) => {
return callingAxios(url)
}

Angular variable assign value if/else inside subscribe getting undefined

here is my complete code function example:
public scan(formData: Object): Observable<any> {
let url = this.remoteUrl;
let result;
this.onlineService.isOnline$.subscribe( (isOnline) => {
if (isOnline) {
console.log('services is online connected');
result = this
._http
.post(url, formData, { headers: headers })
.pipe(map((res: any) => {
// console.log(res);
let response = res;
return response;
}),
catchError(error => {
if (error.status === 401 || error.status === 403) {
// handle error
}
return throwError(error);
}));
}else{
console.log('services are offline');
result = this.dbService.getByIndex('safety', 'code', formData['trafoStation']).subscribe( (location) => {
return location;
});
}
});
console.log(result);
return result;
};
actually, I need to run two different services based on an internet connection if the connection is available then call server API otherwise store on offline ngx-indexed-db.
i have stored data both online and offline.
getting undefined in result.
Result is undefined because it's an async operation: this.onlineService.isOnline$ has not emmited yet, but you already have return result, thus the undefined.
Also, the way you combine your observables is not right. You should NOT create new observables (and subscribe to them) in a subscribe method. That lead to weird side effects and memory leaks down the line.
Here's my proposal to get your code to work. I used the switchMap operator to return either your apiCall or your store operation based on isOnline$ value. SwitchMap is used to combine a higher observable with an inner observable and flatten the stream. It will also interupt the current subscription each time isOnline$ emits:
private _handleServices(formData, isOnline: boolean): Observable<any> {
console.log(`services are ${isOnline ? 'online': 'offline'}`);
const url = this.remoteUrl;
const apiCall$ = this._http.post(url, formData, { headers: headers })
.pipe(
catchError(error => {
if (error.status === 401 || error.status === 403) {
// handle error
}
return throwError(error);
})
);
const store$ = this.dbService.getByIndex('safety', 'code', formData['trafoStation']);
return (isOnline) ? apiCall$ : store$;
}
public scan(formData: Object): Observable<any> {
return this.onlineService.isOnline$.pipe(
switchMap((isOnline) => this._handleServices(formData, isOnline)),
tap(res => console.log(res))
);
};
Then, when you call your function in your component, you will call it like this:
this.scan(formData).subscribe(res => /* handle scan response */);

How to process the Promise returned from parent Promise chain with various possible outcomes

In my Node.JS web app, I have a database layer module (db_location.js). Depending the response type from the node-fetch call, it returns a json() or a text() promise depending on the content type from the response of the fetch call.
const querystring = require('querystring');
const fetch = require('node-fetch');
const p_conf = require('../parse_config');
const db_location = {
getLocations: function() {
return fetch(`${p_conf.SERVER_URL}/parse` + '/classes/GCUR_LOCATION', { method: 'GET', headers: {
'X-Parse-Application-Id': 'APPLICATION_ID',
'X-Parse-REST-API-Key': 'restAPIKey'
}}).then(function(res1) {
const contentType = res1.headers.get('content-type').toLowerCase();
if (contentType.includes("application/json"))
return res1.json(); // RETURNS A PROMISE
else
return res1.text(); // RETURNS A PROMISE
}).catch(err => Promise.reject(JSON.stringify({ "Error": err })));
}
};
module.exports = db_location
The module is called by a Express route locations.js.
const db_location = require('../db/db_location');
router.get('/', function(req, res, next) {
db_location.getLocations()
.then(function(result) {
/*
IF RESULT IS JSON, DO PROCESSING 1;
ELSE RESULT IS TEXT, DO PROCESSING 2.
*/
})
.catch((err) => {
return next(err);
})
});
As the response from the fetch cannot be passed down the promise chain, there is no way to retrieve the content type from in the route code.
Well Javascript strings are valid Json data. So in theory you can't really tell whether something was Json or not unless you transform it after res1.json()
You can check if something is of type string with the following in location.js
if(typeof result === 'string'){ /* it's a string*/ }
else{ /* it's something else */}

Http Post using .map doesnt work when service return Http 400

From my Typescript code, I invoke a webservice written in C#. My typescript code looks like this, and it works as expected when my service returns HTTP200, but when the server rejects the credentials and throws HTTP 400, it will not break inside the map function.
return this.http.post(this.authenticationEndpoint, params)
.map((response:Response) => {
let resp = response;
let token = response.json() && response.json().access_token;
if(token){
this.token = token;
localStorage.setItem('user', JSON.stringify({userName: userName, token:token}));
return true;
}
return false;
})
Looking at the definition of the Response class this defines properties like status, statusText and so on. Given my limited knowledge of Angular and Typescript I would assume that regardless of the Http code returned from my service, it will break inside the map function? How can I handle this case? My function return an Observable<boolean>
You need to catch the Observable Errors here's an Example:
export class ApiGateway {
baseURL = "https://myapi.com"; // or sometimes pulled from another file
constructor(private http: Http) {}
get(path, params) {
showLoadingIndicator();
let headers = this.createMySpecialHeaders();
let options = {
headers: headers
} // and whatever else you need to generalize
let fullUrl = this.baseUrl + path + '?' + this.urlEncode(params)
`;
return this.get(path, params, options)
.do(() => hideLoadingIndicator())
.map(res => res.json())
.catch(err => {
hideLoadingIndicator();
// show error message or whatever the app does with API errors etc
// sometimes rethrow the error, depending on the use case
})
}
}

ngrx/effect passing data to the operators

I have a scenario where I have to get the request payload passed when the service fails so I can return back along with error response. My code goes like below.
#Effect() doGetEvents$: Observable<Action> = this.actions$
.ofType(EVENTS)
.switchMap((action) => {
let eventDate = action.payload.date;
return this.http.service(action.payload);
})
.map(res => {
// success
if (res.status) {
return CustomActions.prototype.eventsResponse({ type: EVENTS_RESPONSE, payload: res.payload });
}
//failure
return CustomActions.prototype.EventsErrorResponse({
type: CustomActions.EVENTS_ERROR_RESPONSE,
payload: {
status: res.status,
errorMessage: res.errorMessage,
billDate: '10/01/2016', // <--- I need the eventDate got from the above switchMap
errorType: CustomActions.EVENTS + '_ERROR'
}
});
});
I tried passing like
.switchMap((action) => {
let eventDate = action.payload.date;
return [eventDate, this.http.service(action.payload)];
})
but this won't execute the http call and won't return the response on .map() args.
Also the are options to make the eventDate outside the scope of Effects and assign it when service fails but it is not a cleaner approach, there should be some way passing data round not sure what I missed!
If you want to include information from the payload, along with the HTTP service's result, you can use the map operator, like this:
.switchMap((action) => {
return this.http
.service(action.payload)
.map(result => [action.payload.date, result]);
})
.map(([date, result]) => { ... })

Categories