Angular2 HTTP Get Observable - How to wait for result - arrays

I am trying to validate a user token by the means of a back-end API. I am brand new to Angular2 in general. My question is, if I want isValidToken to return a boolean value of whether or not the token provided was valid, how can I wait for the HTTP call to complete prior to return in result from isValidToken()?
isValidToken(token: string): boolean {
var isValidToken: boolean = false;
this.getIsValidToken(token).subscribe(
data => {
isValidToken = data.isValidToken;
return isValidToken;
},
error => {
return false;
}
);
}
getIsValidToken(token: string) {
return this.http.get(this.validateTokenUrl + '?tokenString=' + token)
.map(res => res.json());
}

isValidToken needs to return Observable<boolean> or Promise<boolean>. It can't return the value synchronously because it relies on an asynchronous method for it's result.
It's turtles all the way down.

isValidToken(token: string): boolean {
return this.getIsValidToken(token);
}
getIsValidToken(token: string) {
return this.http.get(this.validateTokenUrl + '?tokenString=' + token)
.map(res => res.json());
}
then you can use it like
someMethod() {
this.isValidToken.subscribe(token => {
if(token) {
this.success = true;
// or some other code that should be executed when `token` is `true`
} else {
this.success = false;
// or some other code that should be executed when `token` is `false`
}
},
error => {
this.success = false;
// or some other code that should be executed when `token` is `false`
});
}
You can't go to sync execution from an async call. All you can do is return the observable (or promise) for the caller to be able to subscribe and register a callback to be called when data events are emitted or errors occur.

Related

How can I save a value in this React lambda function?

I have this React project template, it uses Spring for backend and a PostgreSQL database.
Here, I have the name of a caregiver, and what i want, is to get the id of that caregiver.
I don't know how to retrieve the id, from the findCaregiver method. When in the function, "result.id" will show the correct id, but when it returns to "handleSubmit", the initial method, the value is gone. I tried storing it in the current components' state, in a global variable, even in localStorage. But nothing works, after the function is done, the value is gone. Any ideas? Thank you!!
handleSubmit() {
let name = this.state.formControls.caregiverName.value;
let c = this.findCaregiver(name);
console.log("id: " + c);
findCaregiver(name) {
return API_USERS.getCaregiverByName(name, (result, status, error) => {
if (result !== null && (status === 200 || status === 201)) {
console.log("Successfully found caregiver with id: " + result.id);
//result.id shows correct id here!
} else {
this.setState(({
errorStatus: status,
error: error
}));
}
});
}
getCaregiverByName is asynchronous. When you call it, the gears are set in motion, but then the function finishes immediately. Then you return to handleSubmit, and log out nothing, because it isn't done yet.
Some time later, the get finishes, and the callback function will be called. Any code that you need to run when the result is ready needs to be done in that callback, or something called by that callback.
So if we're sticking with callbacks, you can add a callback to findCaregiver:
handleSubmit() {
let name = this.state.formControls.caregiverName.value;
this.findCaregiver(name, (id) => {
console.log("id: " + id);
});
}
findCaregiver(name, callback) {
API_USERS.getCaregiverByName(name, (result, status, error) => {
if (result !== null && (status === 200 || status === 201)) {
callback(result.id);
}
}
}
If you perfer promises to callbacks (most people do), you can instead change your code to return a promise. Perhaps getCaregiverByName could be modified to return a promise, but if you don't have access to that code you can wrap your existing code in a promise like this:
handleSubmit() {
let name = this.state.formControls.caregiverName.value;
this.findCaregiver(name)
.then((c) => {
console.log("id: " + c);
});
}
findCaregiver(name) {
return new Promise((resolve, reject) => {
API_USERS.getCaregiverByName(name, (result, status, error) => {
if (result !== null && (status === 200 || status === 201)) {
resolve(result.id);
} else {
reject(error);
}
})
});
}
And if it's returning a promise, you have the option to use async/await:
asycn handleSubmit() {
let name = this.state.formControls.caregiverName.value;
const c = await this.findCaregiver(name);
console.log("id: " + c);
}

Angular 7/Typescript : Create queue/array of methods

I have a requirements that some functions should be called after some method completes execution.
Below is my code of processing the queue.
processQueue() {
while (this.queue.length) {
var item = this.queue.shift();
item.resolve(item.func(item.types));
}
}
This is one of the sample function to push method in queue
getAllValues() {
let promise1 = new Promise((resolve, reject) => {
if (this.isReady) {
resolve(this._getAllValues());
} else {
this.queue.push({
resolve: resolve,
func: this._getAllValues
});
}
});
return promise1;
}
And this is one of the function which will be called on processing the queue
_getAllValues() {
var results = {}, values = this.enumInstance.enumsCache.values;
for (var type in values) {
if (values.hasOwnProperty(type)) {
results[type] = values[type][this.enumInstance.lang];
}
}
return results;
}
The issue i am facing is when i call _getAllValues() directly then i am able to access this.enumInstance.
But when same method is being accessed through processQueue() i am unable to access this.enumInstance. It gives me undefined. I think this is not referred to main class in this case.
So can anyone help me here. How can i resolve this?

How to return response to calling function in AngularJS?

I am calling this method testDataService, which is defined in the same JS file. This method returns a list which it gets from an API call. I want to set that value to model and return model object. but my return function is getting called before my API returns the response. How can i make sure return function will get called only after the above if block get the data from API.
getTestData(model) {
model.name = "practice";
model.value = 2;
// this if loop is calling an API and setting up data into model.
if(this.model.form.length>0 && this.model.form[0].entityName === 'test'){
let responseList;
this.testDataService(this.model).then(response => {
responseList = response;
model.class = responseList;
});
}
return this.model;
// this return function is getting called before the api returns its data. How can i make sure this return will get called only after the above if block get the data from API.
}
This is method definition
testDataService(model) {
let profileType = "test";
let profileId = "test_profile";
let configCategory = "test";
return this.referenceDataService.getTestData(profileType, profileId, configCategory);
}
You need to pass return statement from the callback, instead of placing it outside.
getTestData(model) {
model.name = "practice";
model.value = 2;
// this if loop is calling an API and setting up data into model.
if (this.model.form.length > 0 && this.model.form[0].entityName === 'test') {
this.testDataService(this.model).then(response => {
let responseList = response;
model.class = responseList;
return this.model;
}).then(response => {
return null;
});
}
}
testDataService(model) {
let profileType = "test";
let profileId = "test_profile";
let configCategory = "test";
return this.referenceDataService.getTestData(profileType, profileId, configCategory);
}

Promises not running T-SQL query in node js

I am trying to write a function in node js that will run a SQL query using mssql and return a promise. For some reason it gets to the line
console.log("got to the run proc functions");
but won't run any code after that. Any help with this issue would be greatly appreciated.
runProc: function (params) {
var sql = require("mssql");
sql.Promise = require('promise');
return new Promise((resolve, reject) => {
var dbConfig = {
server:"ip",
database: "db",
user:"user",
password: "pw"
}
console.log("got to the run proc functions");
var keys = Object.keys(params);
sql.connect(dbConfig).then(pool => {
console.log("got connected");
const request = pool.request()
for (var i = 0; i < keys.length; i++) {
if (keys[i].substring(0,6)=="Common") {
request.input(keys[i],sql.Bit,params[keys[i]]);
console.log("set the bit parameters");
}
else {
request.input(keys[i],params[keys[i]]);
console.log("set the other parameters");
}
}
request.execute("storedprocedure")
return request;
}).then(result => {
resolve(result)
}).catch(err => {
reject(Error(err))
});
sql.close();
});
}
Look where you call sql.close(). i.e. it's being called before request=pool.request etc! So, that would fail for a start.
Also, you are returning request (which isn't a promise) rather than request.execute() (which is a promise) so, the promise would resolve before execute completes
And finally, no need to wrap a promise inside a Promise constructor (not that this breaks your code, but there's no need for it)
Given all that, your code is
runProc: function (params) {
var sql = require("mssql");
sql.Promise = require('promise');
// removed new Promise constructor as sql.connect already returns a promise we can chain to and return
var dbConfig = {
server:"ip",
database: "db",
user:"user",
password: "pw"
}
console.log("got to the run proc functions");
var keys = Object.keys(params);
return sql.connect(dbConfig)
.then(pool => {
console.log("got connected");
const request = pool.request()
for (var i = 0; i < keys.length; i++) {
if (keys[i].substring(0,6)=="Common") {
request.input(keys[i],sql.Bit,params[keys[i]]);
console.log("set the bit parameters");
}
else {
request.input(keys[i],params[keys[i]]);
console.log("set the other parameters");
}
}
// need to return the result of execute, not the request object
return request.execute("storedprocedure")
})
.catch(err => throw new Error(err))
// use Promise#finally - available in all good promise libraries
.finally(sql.close); // sql.close AFTER we're done with it, not before
}
Using the sparkly new async/await promise sugar simplifies the code even more
runProc: async function (params) {
var sql = require("mssql");
sql.Promise = require('promise');
var dbConfig = {
server:"ip",
database: "db",
user:"user",
password: "pw"
}
console.log("got to the run proc functions");
var keys = Object.keys(params);
try {
const pool = await sql.connect(dbConfig);
const request = pool.request();
for (var i = 0; i < keys.length; i++) {
if (keys[i].substring(0,6)=="Common") {
request.input(keys[i],sql.Bit,params[keys[i]]);
console.log("set the bit parameters");
}
else {
request.input(keys[i],params[keys[i]]);
console.log("set the other parameters");
}
}
// need to return the result of execute, not the request object
return await request.execute("storedprocedure");
} catch (err) {
throw new Error(err);
} finally {
sql.close();
}
}

PromiseKit - Optional promise with reload first promise

I read all documentation but I don't response my question with successfull.
I have this scenario
I call the authenticated api point
If the response is 200 to 299 I fullfill
If the response is 401 I call the api for refresh the token
If i refreshed the API token I need to re-call the first api point (for recovery the needed data).
Can you help me with this problem?
Thanks
Use recursion for you needs. Using PromiseKit you can do awesome things. See my flow with refresh token request below. I expect that the code below is self-documented.
// Define here your errors
enum MyErrors: Swift.Error {
case unauthorized
case unknown
}
// Here is your primary function for retrieving remote data
func fetchRemoteData() {
self.primaryRequest()
.then { data in
return self.parsePrimaryRequest(response: data)
}
.done { parsedResult in
// do something here if all chaining is success
}
.recover { primaryRequestError in // this is your case for refresh token
if case MyErrors.unauthorized = primaryRequestError { // if not authorized
self.refreshTokenRequest()
.then { data in
return self.parseRefreshToken(data: data)
}
.done { token in
// do someting with token, save it in secure store (keychain)
self.fetchRemoteData()
}
.catch { refreshTokenError in
// refresh token request has failed
}
}
else {
throw primaryRequestError
}
}
.catch { primaryRequestError in
// here if error during request
}
}
func primaryRequest() -> Promise<Data> {
return Promise { seal in
// here you execure the request
// ...
// ...
let responseData = Data() // here you get data from URLSessionTask etc
let yourRequestStatusCode = 401 // take status code
let successCodes = Array(200...299) // define success codes
let authorizationErrorCode = 401 // define status code which requires performing refresh token request
if successCodes.contains(yourRequestStatusCode) {
return seal.fulfill(responseData)
} else if yourRequestStatusCode == authorizationErrorCode {
throw MyErrors.unauthorized
} else {
throw MyErrors.unknown
}
}
}
func parsePrimaryRequest(response: Data) -> Promise<String> {
return Promise { seal in
// here you parse response
// ...
// ...
let parsedObject = "Awesome result"
seal.fulfill(parsedObject)
}
}
func refreshTokenRequest() -> Promise<Data> {
return Promise { seal in
// here you execure the request to refresh token
// ...
// ...
let responseData = Data() // here you get data from URLSessionTask etc
let yourRequestStatusCode = 401 // take status code
let successCodes = Array(200...299) // define success codes for refresh token request
if successCodes.contains(yourRequestStatusCode) {
return seal.fulfill(responseData)
} else {
throw MyErrors.unknown
}
}
}
func parseRefreshToken(data: Data) -> Promise<String> {
return Promise { seal in
// here you parse response
// ...
// ...
let parsedObject = "00000000-00000000-00000000-00000000"
seal.fulfill(parsedObject)
}
}

Resources