0

I am trying to write a jquery plugin.

Now, I would like to use an ajax-call in one of the functions of this plugin.

However it should be chainable, meaning in this case that the ajax-call should be executed and only after something was returned, the return should happen.

I tried different things but so far I could not make it so that the second function in the chain is really executed after the return value of the ajax call was retrieved;

In this version (see below) I can use

$(document).createDatabase().message();

So, chaining works. But looking at the console log – the message() function is executed before the ajax-call in createDatabase() is finished.

How can I make it so that

$(document).createDatabase().message();

first returns the output/return of the ajax-call that is inside createDatabase() and only after that message() is executed?

Code:

(function($) {

    $.fn.createDatabase = function(options) {

        // Plugin options defaults
        var settings = $.extend({
            name: 'NA',
            onExit: function() {} // callback function
        }, options);

        $.ajax({
                method: "POST",
                url: "plugin/php/createDatabase.php",
                data: settings
        })
        .done(function(msg) {
             console.log("createDatabase executed with message: " + msg);
             settings.onExit.call();    
        });

      return this;

   };



   $.fn.message = function() {

       console.log('this should appear after the console-log message of createDatabase');
       return this;
   }

}(jQuery)); 

Thank You!

grueb
  • 123
  • 11
  • the `return this` will happen long before the ajax completes and `message()` will fire synchronously also. Are you trying to use your own plugin for message also or some third party plugin? – charlietfl Jul 25 '15 at 20:53
  • Yes – that is exactly the problem. I tried to put `return this` into the `.done` function of the ajax-call. But this does not seem to work since `this` is then referring to a different thing, right? `message` is just the second function of the plugin. – grueb Jul 25 '15 at 20:57
  • Should read and understand : http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call . You can't do what you are trying to do. Anything related to the ajax needs to be handled in callback or as promise of the ajax – charlietfl Jul 25 '15 at 20:58
  • Not really clear why you want the chained method for `messag()`. You could use it however in a callback option of the first plugin – charlietfl Jul 25 '15 at 21:02
  • its not so much about `message()` as it is about `createDatabase()` – I want to make that chainable, since it should create some database entries and I need to make sure that these are created before moving on – therefore being able to chain this would be wonderful. – grueb Jul 25 '15 at 21:06
  • Can't chain it by returning `this` which is the norm for all jQuery methods. You could return the `$.ajax` promise but would be unorthodox – charlietfl Jul 25 '15 at 21:07
  • also since example is using `document` as selector...does this really need to be used with an element? No need to do it on `$.fn` if it won;t be element specific. If it was just built in `$.createDatabase()` it wouldn't matter what you returned – charlietfl Jul 25 '15 at 21:11
  • Can't help a lot more without a much higher level overview of objectives updated in question – charlietfl Jul 25 '15 at 21:13
  • Thanks! I guess you are right – `$.createDatabase()` would suffice. The only objective I have is to make `$.createDatabase()` chainable – but because of the ajax-call inside it I want to make it synchronous to that .. i.e. that the chain continues only after the ajax call was executed completely – grueb Jul 25 '15 at 21:39
  • have you not tried setting `async: false` on your ajax settings? – swatkins Jul 25 '15 at 21:42
  • @swatkins `async:false` is being deprecated by browser vendors...and for good reason. It completely blocks the UI and all scripts and that is why it has been recognized as terrible practice for a long time. try using it will see warnings in console in some browsers now – charlietfl Jul 25 '15 at 21:54
  • @charlietfl - I agree that `async:false` is not best practice. But the op is wanting to run an ajax request synchronously. This still stands as a viable option. – swatkins Jul 25 '15 at 22:35
  • @swatkins not in light of deprecation it doesn't. Using a deprecated bad practice to circumvent something that should be handled differently in the first place doesn't make sense – charlietfl Jul 25 '15 at 22:37
  • @charlietfl - not here to get in a philosophical debate on the use of deprecated options. I agree with you that you should not block the UI. However, the op's decision to block the UI is his/her decision and he/she assumes those risks. Therefore, until jQuery removes `async:false` as an option, this would work for the op. – swatkins Jul 25 '15 at 22:50

1 Answers1

0

You could do a couple of things, but they are all a bad idea. The reason is that these are two separate jQuery plugins - a plugin should be capable of working on its own. There is no guarantee or reason that somebody won't do .message().createDatabase(). If you need to guarantee the order of execution, then you should use just one plugin. One possible way would be to pass message inside options when you call .createDatabase(options), and then run message when the call is done. Like so

$(document).createDatabase({
    message: function() {...}
});
...
var promise = $.ajax({
            method: "POST",
            url: "plugin/php/createDatabase.php",
            data: settings
    })
    .done(function(msg) {
         console.log("createDatabase executed with message: " + msg);
         settings.onExit.call();    
    });
...
if ( settings.message )
    promise.done( settings.message.bind(this) );

I tried different things but so far I could not make it so that the second function in the chain is really executed after the return value of the ajax call was retrieved;

The second function executes when the first one finishes. The first one finishes with return this, but this happens before the ajax call is done because ajax calls are asynchronous.

nomve
  • 736
  • 4
  • 14