0

I had such API for async requests

 request(pathParams, params, method, callback, error) {
 ...........
 return $.ajax({
 ...requestAttrs,
 url: url,
 data: params,
 xhrFields: {
 withCredentials: true
 },
 type: method,
 success: callback,
 error: error
 })
 }

But due to some requirements I need to change it to

request(pathParams, params, method, callback, error) {
 ...........
 someAsyncFunction(function(){
 return $.ajax({
 ...requestAttrs,
 url: url,
 data: params,
 xhrFields: {
 withCredentials: true
 },
 type: method,
 success: callback,
 error: error
 }) 
 })
 }

I hope you see my problem. In the previous case I was using the value returned from $.ajax call - for example because I would cancel those requests.

But now when I need to put my ajax function inside another async function, I can't return the $.ajax value like I did previously (because now I moved return inside someAsyncFunction).

Is there a way I could possibly first run that someAsyncFunction inside request, wait for its completion and then return $.ajax as I was doing before?

is something like stratified.js library usable for this?


someAsyncFunction is updateToken function from here. Basically I need to put what I had in request before, inside the success callback of updateToken - but the problem is I can't return the $ajax now as I did before.

asked Jan 11, 2018 at 8:12
17
  • it really depends on what the heck myAsyncFunction actually does - without knowing that, the answer is potato Commented Jan 11, 2018 at 8:15
  • @JaromandaX It is updateToken function from keycloack (keycloak.org/docs/3.1/securing_apps/topics/oidc/…). and basically I need to put what was before in request in success callback of that updateToken. Commented Jan 11, 2018 at 8:24
  • if you return someAsyncFunction(function() { ...}) and someAsyncFunction returns the result of the callback, which is the return value of $.ajax, then you'll be golden Commented Jan 11, 2018 at 8:24
  • I don't see someAsyncFunction in that page you linked to - so, potato Commented Jan 11, 2018 at 8:25
  • @JaromandaX See updated question please. Commented Jan 11, 2018 at 8:29

3 Answers 3

2

I took the liberty to change your code a little bit.

My approach is to separate code as much as possible so you don't get into the Callback Hell.

  1. Create someAsyncFunction and make whatever you judge necessary so then you can return its value

  2. Same applies to your ajax call. In case it needs the output from someAsyncFunction then it's very easy to send them as well

  3. Promise for the win! Chain all your calls and keep your code's flow :)

I'm using setTimeout so they look asynchronous

function someAsyncFunction() {
 return new Promise(resolve =>
 setTimeout(() => {
 console.log('-> someAsyncFunction has finished')
 
 const token = 'abc123'
 resolve(token)
 }, 1000)
 ) 
}
function executeAjaxRequest(pathParams, params, method, token) {
 return new Promise(resolve => {
 setTimeout(() => {
 console.log('-> executeAjaxRequest has finished')
 resolve()
 }, 2000)
 })
}
function request(pathParams, params, method) {
 someAsyncFunction()
 .then((token) => executeAjaxRequest(pathParams, params, method, token))
 .then(() => console.log('-> end!'))
}
request('pathParams', 'params', 'method')

Sample code someAsyncFunction and keycloak thing :)

function someAsyncFunction() {
 return new Promise((resolve, reject) => {
 keycloak.updateToken(30)
 .success(resolve)
 .error(reject)
 })
}
answered Jan 11, 2018 at 8:46
Sign up to request clarification or add additional context in comments.

16 Comments

please check updated question (bottom) where I specify what someAsyncFunction is.
@user200300 It doesn't matter what someAsyncFunction is or does. As long as you call resolve when it finishes you are good to go :)
@mersocarlin: It kind of does matter: his someAsyncFunction is actually a function that returns a promise (and does not take a callback like in his example code), so manually constructing a promise and resolving it is not even needed.
I was using return value of $.ajax before because I needed to cancel (e.g. using .abort()) those requests sometimes, can I still do that?
That is not "taking a callback". Taking a callback: foo(callback). Returning a promise: foo().then(callback). With a promise, then takes a callback, not your function. They are two very distinct patterns.
|
2

OK, I see where your problem is. Apologies for not thinking it through. The jqXHR that $.ajax returns functions in two ways: both as a promise, and also as a handle where you can abort it before it is done. The first requires we return it, so that we can continue the promise chain. The second requires we retain it, so we can get at it outside the promise chain.

function authenticateWithKeycloak() {
 return new Promise((resolve, reject) => {
 keycloak.updateToken(30)
 .success(resolve)
 .error(reject)
 })
} 
function request(...) {
 let promise = authenticateWithKeycloak();
 promise.abort = () => { promise.aborted = true; }
 return promise.then(authenticated => {
 if (!promise.aborted) {
 let xhr = $.ajax({...});
 promise.abort = () => xhr.abort();
 }
 return promise;
 })
}
let reqPromise = request(...);
reqPromise.then(...);
reqPromise.abort();

EDIT: allowed aborting before AJAX.

answered Jan 12, 2018 at 6:26

7 Comments

one question: when I call abort as above, what if the we are in the middle of updateToken call? what will it abort then?
It would raise an error, because xhr would not exist yet. We can fake a NOP-on-abort xhr before, with promise.xhr = { abort: () => void 0 } before promise.then. Or you can check existence of xhr before trying to abort. There might be more options.
Ah so it is tricky actually because before I was relying a lot on the abort functionality to avoid some race conditions. But now if user does abort, there is a chance that the operation he/she intended to abort will not abort, because, say he/she clicked abort at the wrong time? (i.e. at the time when updateToken was running). is my reasoning above correct?
I see what you mean. How about now?
Out of interest, I think we could have also done this without promises, e.g. using something like this: codepad.org/HNaV2TfK
|
-1

You may want to do like this. Hope this fits your case. If I misunderstood it, pls ping in the comment.

Here, I just returned a string, you can edit to return the ajax request.

function someAsyncFunction(callback)
{
 //do something
 
 return callback();
}
function request(pathParams, params, method, callback, error) {
 return someAsyncFunction(function(){
 return "Ajax request"; 
 });
}
console.log(request());

answered Jan 11, 2018 at 8:37

1 Comment

please see updated question where I specify what someAsyncFunction is

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.