PromiseKit - Optional promise with reload first promise - promisekit

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

Related

In angular js application how to make other codes wait until some code are done?

In angular js application, if have to send a request to the database, and until response comes no other actions should be done, Now I am not able to do that
function checkStep() {
if (currenctStep == 1 && checkBalance()) { // request database to check balance
alert('balance is not enough');
} else if (currentStep == 2) {
goToNextStep();
} else if (currentStep == 3) {
validateAll();
}
// ... some actions should wait until above codes are executed,
// here some codes that do some actions and should change current step after
// checkBalance() respose comes
}
What can I do in order to make all other codes wait until the response comes in checkBalance()
checkBalance is a async call, ti should return a promise.
Something like:
function checkStep() {
if (currenctStep == 1) { // request database to check balance
checkBalance().then(function (response) {
// parse response data
if (currentStep == 2) {
goToNextStep();
} else if (currentStep == 3) {
validateAll();
}
}, function (error) {
// failed to call DB
});
}
// ... some actions
}
where checkBalance can be:
function checkBalance() {
// some call DB here
return $http({method: 'GET', url:URL}).then(function (result) {
return result;
}, function (error) {
console.error(error);
return $q.reject(error);
});
};

Proper way to err out of PromiseKit

What is the proper way to throw an error from a function like this:
func fetch(by id: String, page: Int = 1) -> Promise<ProductReviewBase> {
// call api
guard let url = URL(string: "") else {
return Promise { _ in return IntegrationError.invalidURL }
}
return query(with: url)
}
I'm confused whether to make this a function that throws an error, or return a promise that returns an error. Thanks
I really hate interfaces that mix metaphors. If you are going to return a promise, then use the promise's error system. If you want more justification than my hatred, then visualize what it would look like at the call site:
do {
(try fetch(by: id))
.then {
// do something
}
.catch { error in
// handle error
}
}
catch {
// handle error
}
vs
fetch(by: id)
.then {
// do something
}
.catch { error in
// handle error
}
The latter looks a whole lot cleaner.
Here's the best way (IMO) to write your example function:
func fetch(by id: String, page: Int = 1) -> Promise<ProductReviewBase> {
guard let url = URL(string: "") else { return Promise(error: IntegrationError.invalidURL) }
return query(with: url)
}

Angular2 HTTP Get Observable - How to wait for result

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.

how to get JSON array value from internet

I want to get value of an array from JSON code in internet. from this URL : http://olympics.clearlytech.com/api/v1/medals/
after that, I want to display that array of my script without rewrite that JSON code on this URL http://olympics.clearlytech.com/api/v1/medals/
so, what code (script) that I can use?
for example, I want to display value from this array
var JSONs = {
example:['one','two','three']
};
the code is
document.write(JSONs.example[0]);
but if I want get the array value from the internet, what code/script that I can use?
Using jQuery, here is an example. In the success event, turn the resulting json text into a json object. You could also set the content type as json so you wouldn't have to call the JSON.parse().
$.ajax({
url: "http://olympics.clearlytech.com/api/v1/medals/",
success: function(data) {
var json = JSON.parse(data);
}
});
This is another way of doing the same i hope you asked how to parse through each value just try this in jsfiddle
$(document).ready(function(){
alert("here");
$.getJSON("http://olympics.clearlytech.com/api/v1/medals/",function(data){
$.each(data,function(key,value){
alert(data[key].country_name);
alert(data[key].rank);
console.log(data[key].rank));
});
});
});
public void handleResponse(String response)
{
// display("Response:"+response);
if(!response.equalsIgnoreCase(""))
{
JSONObject jso;
try {
jso = new JSONObject(response);
String status = jso.getString("status");
int valid=jso.getInt("valid");
// display("Welcome : "+UName);
if(valid>0)
{
if( status.equalsIgnoreCase("") || status==null || status.equalsIgnoreCase("Failed"))
{
invalid.setText("Invalid password");
//reset();
pwd.setText("");
}
else
{
//display(status);
intObj=new Intent(MainActivity.this,Design_Activity.class);
intObj.putExtra("Username", mUname);
startActivity(intObj);
MainActivity.this.finish();
}
}
else
{
invalid.setText("Invalid userid");
uname.setText("");
}
}
catch (JSONException e1) {
// TODO Auto-generated catch block
Log.e(TAG, e1.getLocalizedMessage(), e1);
}
catch(Exception e)
{
Log.e(TAG, e.getLocalizedMessage(), e);
}
}
else
{
display("Could not able to reach Server!");
}
}
Althought you want us to do everything, thats why your question went negative. Anyhow this is how you can do it in plain ajax
function getData(){
// Initialize the Ajax request
var xhr=new XMLHttpRequest();
xhr.open('get', 'http://olympics.clearlytech.com/api/v1/medals/');
// Track the state changes of the request
xhr.onreadystatechange=function(){
// Ready state 4 means the request is done
if(xhr.readyState === 4){
// 200 is a successful return
if(xhr.status === 200){
alert(xhr.responseText); // 'This is the returned text.'
}else{
alert('Error: '+xhr.status); // An error occurred during the request
}
}
}
// Send the request to send-ajax-data.php
xhr.send(null);
}

Angular how to deal with unavailable URLs requested by $http.get or $http.jsonp, which are executed by $q.all()

I've the following code:
eventResourcesCall = $http.jsonp('https://apicall/to/serverA');
eventsDetailsCall = $http.get('https://apicall/to/serverB');
$q.all([eventResourcesCall, eventsDetailsCall]).then(function(values){
//process data manipulation and merging
});
The problem is that serverA and ServerB might not be available sometimes, and when one of those are unavailable, the data processing code stops and I get an error similar to the one described below:
GET https://apicall/to/serverA?jsonp=angular.callbacks._0 404 (Not Found)
Can any one point me to a documentation or describe on the answer how to properly deal with unavailable URL requested by $http and executed by $q.all()?
What I would like to be able to do is to get an indication that the URL is not accessible and then avoid the data processing code abortion.
Thanks!
I would use indirect promises:
var d1 = $q.defer(), d2 = $q.defer();
function NetworkError(reason) { this.reason = reason; }
eventResourcesCall = $http.jsonp('https://apicall/to/serverA').then(
function(response) {
d1.resolve(response);
},
function(err) {
d1.resolve(new NetworkError(err));
}
);
eventsDetailsCall = $http.get('https://apicall/to/serverB').then(
function(response) {
d2.resolve(response);
},
function(err) {
d2.resolve(new NetworkError(err));
}
);
$q.all([d1, d2]).then(function(values){
var eventResources = values[0], eventsDetails = values[1];
if( eventResources instanceof NetworkError ) {
// handle error
}
else {
// eventResources is good, use it
}
// and so on...
});
So the indirect promises are allways resolved and the all() succeeds. But the resolution value may be of the special NetworkError class which signals the actual error in this request.
This is definitely bulky, but could be improved with some utility methods, e.g.:
function makeIndirectPromise(httpPromise) {
var ret = $q.defer();
httpPromise.then(
function(response) {
ret.resolve(response);
},
function(err) {
ret.resolve(new NetworkError(err));
}
);
return ret.promise;
}
And the code above changes to:
function NetworkError(reason) { this.reason = reason; }
function makeIndirectPromise(httpPromise) { /* see above */ }
eventResourcesCall = makeIndirectPromise($http.jsonp('https://apicall/to/serverA'));
eventsDetailsCall = makeIndirectPromise($http.get('https://apicall/to/serverB'));
$q.all([eventResourcesCall, eventsDetailsCall]).then(function(values){
var eventResources = values[0], eventsDetails = values[1];
if( eventResources instanceof NetworkError ) {
// handle error
}
else {
// eventResources is good, use it
}
// and so on...
});
From Angular doc to $q: as $http returns a promise, you can catch promise rejection using either:
$q.all([eventResourcesCall, eventsDetailsCall]).then(function(values){
//process data manipulation and merging on Success
}).catch(function(errors){
//Deal with your $http errors
}).finally(function(data){
});
or
$q.all([eventResourcesCall, eventsDetailsCall]).then(function(values){
//process data manipulation and merging on Success
}, function(errors){
//Deal with your $http errors
});

Resources