Call recursive function in Observable not working in ionic3 - ionic-framework

I have one function in my app getServerData() which I call from home page and passing Token as param in my API calling in this function.
if Token is valid API will return data otherwise it will return unauthorised access with token expired error at that time I am calling same function with new generated token form another API but some how recursive function calling not working in Observable.
Check below code for more detail :
/**
* Get Search result from server.
*/
getServerData(searchText: string): Observable<any> {
let self = this;
return Observable.create(function(observer) {
self.getToken().then((token) => {
console.log('Token : ', token);
self.httpPlugin.get(self.url + searchText, {}, {}).then((response) => {
console.log("Response Success : " + JSON.stringify(response));
observer.next(jsonResponse);
}).catch(error => {
if (error.status == 403) {
//Call Same method Again
self.getServerData(searchText);
} else {
console.log("Error : " + error);
console.log("Error " + JSON.stringify(error));
observer.error(error);
}
});
}).catch((error) => {
observer.error(error);
console.log("Error : " + error);
})
});
}
While calling same function no code execution done.
Edit based on comment:
I am subscribe like below:
this.subscription = this.api.getServerData(this.searchString.toUpperCase()).subscribe((response: any) => {
console.log("back with data :-",response);
}, error => {
console.log("InLine Error : ",error);
});
Not able to understand whats going wrong or Am I doing some mistake in calling function from Observable().
Guide me on this.
Thanks in advance!

It's not good practice to use promise in observable. Use Obserable.fromPromise and also use mergeMap. What will happen if you will use. Whenever any error will come Observable will throw error and you will able to catch. I will suggest to use Subject rather than creating your own observable and also remember one thing that don't subscribe in your service.
Hope it will help

Finally after lots of research I found solution of my issue.
1st thing was I need to update my rxjx library as my installed version of rxjx was 5.5.2 so I upgraded it to latest one 5.5.11.
2nd thing was I am calling Observable without subscribe() to that Observable so it will never return so I updated my recursive call from error block from where I call its subscriber() like below.
getSearchData(){
this.subscription = this.api.getServerData(this.searchString.toUpperCase()).subscribe((response: any) => {
console.log("back with data :-",response);
}, error => {
if (response.status == 403) {
this.getSearchData();
}else{
console.log("InLine Error : ",response);
this.showAlert('Error', 'Something went wrong. please try again.');
}
});
}
By doing above 2 things I am able to solve my issue.
Thanks all for your quick reply on my issue.
Hope this will help someone who is facing same issue like me.

Related

Ionic view not updating after return from provider promise

I'm very new to Ionic and JS programming in general so please forgive my ignorance. I've been able to get data from other REST providers I've setup and have the updated values display fine. Pretty much copied the code from some other working functions. This time, no matter what I try, nothing will update.
Provider:
return new Promise(resolve => {
this.http.post(this.apiUrl)
.subscribe(res => {
resolve(res);
},
(err: HttpErrorResponse) => {
if (err.error instanceof Error) {
this.error = {"text":"App error occured."};
console.log('Client-side error occured.');
} else {
this.error = {"text":"Cloud server error occured."};
console.log('Cloud server error occured:'+err);
}
return this.error;
});
});
}
HTML:
<ion-item>
<ion-label stacked>Make</ion-label>
{{vesselData?.make}}
</ion-item>
Function:
vesselData = {"make":""};
updateVesselInfo() {
const data = JSON.parse(localStorage.getItem('userData'));
this.vesselProvider.getVesselData(data.userData.sim).then(vData => {
this.vesselData = vData;
}).catch(console.log.bind(console));
}, (err) => {
console.log("Vessel: ".err);
});
If I log the data returned from the provider in the .then(), it shows the provider returned the correct data. However, it's not updating any of the vesselData variables. Any idea where I'm going wrong here?
So modern way is to provide method in your provider that returns Observable and then in your component you just call this method and subscribe to it to obtain data:
In your provider:
getVesselData() {
return this.http.post(this.apiUrl)
.pipe(
catchError(this.yourErrorHandlerInsideProviderHere)
)
}
Now in your component:
vesselData = {"make":""};
updateVesselInfo() {
this.provider.getVesselData().subscribe( vesselData => {
this.vesselData = vesselData;
})
}
So ideal is to keep error handling inside provider here and within component your methods should be light weight.
This example should work for you as long as you are on Angular 4.3+ using modern HTTP module that comes with it.
Update:
Please ensure you properly bind to template. Here is example:
https://stackblitz.com/edit/ionic-wqrnl4
I skipped the rest call (http), but the principle is the same.

protractor browser.executescript does not return a value

I'm trying to run the following scripts in Protractor
browser.executeScript("return window.localStorage.getItem('access_token');").then((accessToken) => {
console.log("AccessToken Obtained ", accessToken);
});
However the code never goes into the .then section. It just gets blocked. I tried executeAsyncScript and still the same result.
I went through a lot of online examples and I think this should work, however not sure whats going wrong here.
Could you try this one:
function getAccessToken() {
return window.localStorage.getItem('access_token');
}
browser.executeScript(getAccessToken).then((accessToken) => {
console.log("AccessToken Obtained ", accessToken);
});

TypeError seneca indexof if not a function during respond

I have written a simple action which connects to mongo db using seneca-mongo store module, execute a list query and get the results. I can see that the query was successful and the correct results were fetched. When I try to send these results back to the client, the respond call errors out with following message and stack trace.
ERROR act root$ OUT cmd:getparams,role:diff 11 {cmd:getparams,role:diff,payload:{id:scalaScan}} ENTRY (dqk22) - seneca: Action cmd:getparams,role:diff callback threw: k.indexOf is not a function. act_callback {message:k.indexOf is not a function,pattern:cmd:getparams,role:diff,instance:Seneca/0.7.2/d0twcki9cmxg/1485517 TypeError: k.indexOf is not a function
at /scratch/DiffAnalyzer/node_modules/seneca/node_modules/seneca-web/web.js:851:13
at Function.forEach (/scratch/DiffAnalyzer/node_modules/lodash/dist/lodash.js:3298:15)
at Object.defaultmodify [as modify] (/scratch/DiffAnalyzer/node_modules/seneca/node_modules/seneca-web/web.js:850:7)
at respond (/scratch/DiffAnalyzer/node_modules/seneca/node_modules/seneca-web/web.js:654:22)
at Seneca.<anonymous> (/scratch/DiffAnalyzer/node_modules/seneca/node_modules/seneca-web/web.js:401:7)
at act_done (/scratch/DiffAnalyzer/node_modules/seneca/seneca.js:1554:16)
at /scratch/DiffAnalyzer/node_modules/gate-executor/gate-executor.js:127:20
at Seneca.<anonymous> (/scratch/DiffAnalyzer/analyze.js:613:5)
at act_done (/scratch/DiffAnalyzer/node_modules/seneca/seneca.js:1554:16)
at /scratch/DiffAnalyzer/node_modules/gate-executor/gate-executor.js:127:20
at /scratch/DiffAnalyzer/node_modules/seneca-mongo-store/mongo-store.js:329:21
at /scratch/DiffAnalyzer/node_modules/mongodb/lib/mongodb/cursor.js:271:33
at /scratch/DiffAnalyzer/node_modules/mongodb/lib/mongodb/cursor.js:778:35
at Cursor.close (/scratch/DiffAnalyzer/node_modules/mongodb/lib/mongodb/cursor.js:1009:5)
at Cursor.nextObject (/scratch/DiffAnalyzer/node_modules/mongodb/lib/mongodb/cursor.js:778:17)
at Cursor.each (/scratch/DiffAnalyzer/node_modules/mongodb/lib/mongodb/cursor.js:264:12)
The action that I have written is
seneca.add("role:diff,cmd:getparams", function(msg, respond) {
seneca.ready(function() {
var collection = seneca.make$("paramStore");
var f = msg.payload;
seneca.log.info("Filter", f);
collection.list$(f, function(err, ob) {
if (err) {
seneca.log.error(err);
respond(err);
} else {
seneca.log.info("Result", ob);
respond(null, ob);
}
});
});
});
The same piece of code was working and now I am getting this error. Not sure what changed. Any help/suggestions are greatly appreciated.
The issue I was facing was because of this bit of code in the module's js file
if( _.isObject( result.out ) ) {
_.each(result.out,function(v,k){
if(~k.indexOf('$') && 'http$' !== k) {
delete result.out[k]
}
})
The _.each function is meant to parse a JSON object, where in my case the out was actually a JSON array. Wrapping the array into an object resolved it.

Baasbox and Javascript

I'm trying BaaSbox, a free Backend as a Service. But it has no out-of-the-box Javascript support I can use right away (yet, only iOS and Android)
I'm having trouble sending the right curl command from javascript, anyone happen to know a good resource or a simple working $.ajax template? I've tried a few examples from stackoverflow, but none of them specifically aimed at BaaSbox.
I've tried following the Java instructions on their site here. Just making a simple login work, but I keep getting the wrong responses from the server.
Or on the other hand, anyone know a good, free alternative to BaaSbox? I just want to be able to install it on my own server, no paid plans or whatever.
in the download page there is a preliminary version of the JS SDK (added few days ago).
The documentation is on the way, however in the zip file you can find a simple example.
For example to perform a signup:
//set the BaasBox parameters: these operations initialize the SDK
BaasBox.setEndPoint("http://localhost:9000"); //this is the address of your BaasBox instance
BaasBox.appcode = "1234567890"; //this is your instance AppCode
//register a new user
BaasBox.createUser("user", "pass", function (res, error) {
if (res) console.log("res is ", res);
else console.log("err is ", error);
});
Now you can login into BaasBox
//perform a login
$("#login").click(function() {
BaasBox.login("user", "pass", function (res, error) {
if (res) {
console.log("res is ", res);
//login ok, do something here.....
} else {
console.log("err is ", error);
//login ko, do something else here....
}
});
Once the user is logged in he can load the Documents belonging to a Collection (the SDK automatically manages the Session Token for you):
BaasBox.loadCollection("catalogue", function (res, error) { //catalogue is the name of the Collection
if (res) {
$.each (res, function (i, item) {
console.log("item " + item.id); //.id is a field of the Document
});
} else {
console.log("error: " + error);
}
});
However under the hood the SDK uses JQuery. So you can inspect it to know how to user $.ajax to call BaasBox.
For example the creatUser() method (signup) is:
createUser: function (user, pass, cb) {
var url = BaasBox.endPoint + '/user'
var req = $.ajax({
url: url,
method: 'POST',
contentType: 'application/json',
data: JSON.stringify({
username: user,
password: pass
}),
success: function (res) {
var roles = [];
$(res.data.user.roles).each(function(idx,r){
roles.push(r.name);
})
setCurrentUser({"username" : res.data.user.name,
"token" : res.data['X-BB-SESSION'],
"roles": roles});
var u = getCurrentUser()
cb(u,null);
},
error: function (e) {
cb(null,JSON.parse(e.responseText))
}
});
}

How can I send a success status to browser from nodejs/express?

I've written the following piece of code in my nodeJS/Expressjs server:
app.post('/settings', function(req, res){
var myData = {
a: req.param('a')
,b: req.param('b')
,c: req.param('c')
,d: req.param('d')
}
var outputFilename = 'config.json';
fs.writeFile(outputFilename, JSON.stringify(myData, null, 4), function(err) {
if(err) {
console.log(err);
} else {
console.log("Config file as been overwriten");
}
});
});
This allows me to get the submitted form data and write it to a JSON file.
This works perfectly. But the client remains in some kind of posting state and eventually times out. So I need to send some kind of success state or success header back to the client.
How should I do this?
Thank you in advance!
Express Update 2015:
Use this instead:
res.sendStatus(200)
This has been deprecated:
res.send(200)
Just wanted to add, that you can send json via the res.json() helper.
res.json({ok:true}); // status 200 is default
res.json(500, {error:"internal server error"}); // status 500
Update 2015:
res.json(status, obj) has been deprecated in favor of res.status(status).json(obj)
res.status(500).json({error: "Internal server error"});
In express 4 you should do:
res.status(200).json({status:"ok"})
instead of the deprecated:
res.json(200,{status:"ok"})
Jup, you need to send an answer back, the simplest would be
res.send(200);
Inside the callback handler of writeFile.
The 200 is a HTTP status code, so you could even vary that in case of failure:
if (err) {
res.send(500);
} else {
res.send(200);
}