简体   繁体   中英

wait for async call to finish before firing function in event listener

I am collaborating on a web project with someone who devised a series of .js scripts that act like 'plugins' in the sense that he would like them to be used on other web projects.

Most of these 'plugins' are event listener based, and they listen for clicks on elements with certain 'data' attributes. For example an element with 'data-setdata' will fire, on click, a listener in 'setdata.js':

$('body').on('click', '[data-setdata]', function(e) {
  // do something
});

But one of these plugins, 'ajax.js', fires a 'post' call for AJAX-style loading of content:

$('body').on('click', '[data-ajax]', function(e) {
    $.post(
      //etc
    );
  }
});

... so of course we find ourselves in a situation in which we cannot control the order in wich 'setdata.js' and 'ajax.js' occur .

My initial thought was to get those plugins back into functions, and properly chain them using promises on a main .js

But, is there a way to delay firing the function within an event listener until a certain async action has been fulfilled? pseudocode:

$('body').on('click', '[data-setdata]', function(e) {
  when( ajax call finishes ){
    // do something
  }
});

Thank you

You can use jQuery's ajaxComplete event

let done = false;

$(document).on("ajaxComplete", function(event, jqxhr, settings) {
  if (settings.url === "/path/to/resource" && !done) done = true;
});

$('body').on('click', '[data-setdata]', function(e) {
  if (done) {
    // do something
  } else {
    console.log(done)
  }
});

As explained in this answer: https://stackoverflow.com/a/22125915/5721273 I could use a setTimeout within the plugins, to continuously poll for changes on a flag set by the ajax call completion.

function checkFlag() {
    if(flag == false) {
       window.setTimeout(checkFlag, 100); /* this checks the flag every 100 milliseconds*/
    } else {
      /* do something*/
    }
}
checkFlag();

Of course this is not the proper way of doing it, which would be chaining promises.

But in the specific case-scenario that I described, in which there is a design limitation imposed by someone else, and when I already told this person about it, but still need to find a temporary workaround, this is the correct answer.

You should use ajax's complete option, which executes when the call is completed, no matter if it is successful or not.

$.ajax({
    type: "GET",

    ....

    success: function(data) {
        // do some stuff
    },
    error: function(data) {
        // do other stuff stuff
    },
    complete: function(data) {
        // call your other function here 
    }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM