Jerry
Jerry

Reputation: 1583

Javascript run async method synchronously in a function

I want to create a listener function to listen changes of global variable. The use case is, when I made a ajax call, i flag isAjaxDone variable to false, once its done then flag it to true. So the listener will process something once detected the isAjaxDone is true.

i tried asyc ... await & Promise but i still can't achieve what i want. The entire method still run asynchronously outside, except the method inside asyc ... await & Promise.

Here is what i have tried:

var isAjaxDone = null
var timeout = 0
function listener(){
  let waiter = function(){
    return new Promise(resolve=>{
      setTimeout(() => {
        timeout += 1
        listener()
      }, 100);
    })
  }

  if(isAjaxDone) return true
  if(isAjaxDone === null) return false 
  if(isAjaxDone === false){
    if(timeout < 300){
      return waiter()
    }
    else{
      return "timeout"
    }
  }
}

Implementation:

function checker(){
  var ajaxStatus = listner()
  if(ajaxStatus){
    //...
  }
}

When i call isAjaxDone, it will return me a Promise function instead of boolean.

I prefer not to use Promise...then because the function i wrote is consider as library, I don't want the user wrap a bunch of code inside the then because it will caused some problem to user code structure. Same goes to the Callback.

I would like to let it wait until either return timeout or boolean only, please advise.

Upvotes: 0

Views: 131

Answers (2)

BlueWater86
BlueWater86

Reputation: 1817

Why not use an AJAX API that is already awaitable like fetch? It is polyfillable.

const request = new Request('https://example.com', {method: 'POST', body: '{"foo": "bar"}'});
(async() => {
  const response = await fetch(request);
  return await response.json();
})()

Upvotes: 1

StackSlave
StackSlave

Reputation: 10627

You could do something like:

var xhr = new XMLHttpRequest;
xhr.open('POST', yourURLHere);
var promise = new Promise(function(resolve, reject){
  xhr.onload = function(){
    var o = JSON.parse(this.responseText); // should be `json_encode(['testProperty' => true])`ed response
    if(o.testProperty === true){
      resolve(true);
    }
    else{
      reject(false);
    }
  }
  xhr.send(formData); // you should get used to FormData
});
promise.then(function(resolveResult){
  yourGlobalVar = resolveResult;
});

Of course, I would just make a post function and execute a function when all is complete, like:

function post(url, formData, success, successContext){
  var xhr = new XMLHttpRequest;
  var c = successContext || this;
  xhr.open('POST', url);
  xhr.onload = function(){
    success.call(c, JSON.parse(xhr.responseText));
  }
  xhr.send(formData);
  return xhr;
}

Now you can reuse:

var fd = new FormData;
fd.append('output', true);
// PHP could look like
/* if(isset($_POST['output']) && $_POST['output'] === true){
     echo json_encode(['result' => true]);
   }
*/
post('someURL.php', fd, function(resultObj){
  globalVar = resultObj.result; // should be true since we sent that
});

Upvotes: 1

Related Questions