简体   繁体   中英

JQuery / Javascript inline callback

In tornado we have gen module, that allows us to write constructions like this:

def my_async_function(callback): 
    return callback(1)

@gen.engine 
def get(self): 
    result = yield gen.Task(my_async_function) #Calls async function and puts result into result variable 
    self.write(result) #Outputs result

Do we have same syntax sugar in jquery or other javascript libraries?

I want something like this:

function get_remote_variable(name) { 
    val = $.sweetget('/remote/url/', {}); //sweetget automatically gets callback which passes data to val
    return val
}

Versions of jQuery prior to 1.8 support sync ajax calls via the async: false setting . Its a hack with limitations (no cross-domain or jsonp, locks up the browser), and I would avoid it if possible.

There are several available libraries that provide some syntactic sugar for async operations in Javascript. For example:

...however I don't think anything provides the synchronous syntax you are looking for - there is always a callback involved, because of the way JavaScript works in the browser.

You describe the function as "my_async_function", but the way you use it is synchronous rather than asynchronous .

Your sample code requires blocking -- if "my_async_function" were truly asynchronous (non-blocking), the following line of code self.write(result) would execute immediately after you called "my_async_function". If the function takes any time at all (and I mean any ) to come back with a value, what would self.write(result) end up writing? That is, if self.write(result) is executed before result ever has a value, you don't get expected results. Thus, "my_async_function" must block, it must wait for the return value before going forward, thus it is not asynchronous.

On to your question specifically, $.sweetget('/remote/url/', {}) : In order to accomplish that, you would have to be able to block until the ajax request (which is inherently asynchronous -- it puts the first A in AJAX) comes back with something.

You can hack a synchronous call by delaying the return of sweetget until the XHR state has changed, but you'd be using a while loop (or something similar) and risk blocking the browser UI thread or setting off one of those "this script is taking too long" warnings. Javascript does not offer threading control. You cannot specify that your current thread is waiting, so go ahead and do something else for a minute. You could contend with that, too, by manually testing for a timeout threshold.

By now one should be starting to wonder: why not just use a callback? No matter how you slice it, Javascript is single-threaded. No sleep , no thread.sleep . That means that any synchronous code will block the UI.

Here, I've mocked up what sweetget would, roughly, look like. As you can see, your browser thread will lock up as soon as execution enters that tight while loop. Indeed, on my computer the ajax request won't even fire until the browser displays the unresponsive script dialog.

// warning: this code WILL lock your browser!
var sweetget = function (url, time_out) {
    var completed = false;
    var result = null;
    var run_time = false;
    if (time_out)
        run_time = new Date().getTime();

    $.ajax({
        url: url,
        success: function(data) {
            result = data;
            completed = true;
        },
        error: function () {
           completed = true;
        }
    });                    // <---- that AJAX request was non-blocking

    while (!completed) {  // <------ but this while loop will block
        if (time_out) {
            if (time_out>= run_time)
                break;
            run_time = new Date().getTime();
        }
    }
    return result;
};

var t = sweetget('/echo/json/');
console.log('here is t: ', t);

Try it: http://jsfiddle.net/AjRy6/

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