Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's C#'s await equivalent in javascript/jquery?

I'm using a jQuery library called bootbox

bootbox.dialog({
    title: "Group",
    buttons: {
        success: {
            label: "OK",
            className: "btn-success",
            callback: function () {
                postForm();
            }
        }
    }
});

function postForm() {        
    $.ajax({
        type: "POST",
        url: $("#add-group").val(),
        data: $("#form").serialize(),
        success: function (data) {
            return true;
        },
        error: function (XMLHttpRequest, textStatus, errorThrown) {
            return false;
        }
    });
}

When I click on the "OK" button, unless I return a false value like this:

callback: function () {
    return false;
}

the dialog will close.

In the callback function, I'm calling postForm which is a function that makes an AJAX call to my server side to perform some operation. Depending on the outcome of that operation, I would like to keep the dialog still open.

But because it's an AJAX call, and the result takes a while to come back, the dialog closes immediately after postForm() regardless of my result.

How can I tell javascript to await for the result of the ajax call?

It'll be great if I can do something like this:

callback: function () {
    var result = await postForm();
    return result;
}
like image 416
Null Reference Avatar asked Apr 24 '14 08:04

Null Reference


2 Answers

I think Promises is exactly what you are asking.

.promise()

Return a Promise object to observe when all actions of a certain type bound to the collection, queued or not, have finished. e.g.

var div = $( "<div>" );

div.promise().done(function( arg1 ) {
  // Will fire right away and alert "true"
  alert( this === div && arg1 === div );
});

For more info refer : https://api.jquery.com/promise/

Deferred Promise is closer to async behaviour:

deferred.promise()

The deferred.promise() method allows an asynchronous function to prevent other code from interfering with the progress or status of its internal request. The Promise exposes only the Deferred methods needed to attach additional handlers or determine the state (then, done, fail, always, pipe, progress, and state), but not ones that change the state (resolve, reject, notify, resolveWith, rejectWith, and notifyWith).

If target is provided, deferred.promise() will attach the methods onto it and then return this object rather than create a new one. This can be useful to attach the Promise behavior to an object that already exists.

If you are creating a Deferred, keep a reference to the Deferred so that it can be resolved or rejected at some point. Return only the Promise object via deferred.promise() so other code can register callbacks or inspect the current state.

Example:

function asyncEvent() {
  var dfd = new jQuery.Deferred();

  // Resolve after a random interval
  setTimeout(function() {
    dfd.resolve( "hurray" );
  }, Math.floor( 400 + Math.random() * 2000 ) );

  // Reject after a random interval
  setTimeout(function() {
    dfd.reject( "sorry" );
  }, Math.floor( 400 + Math.random() * 2000 ) );

  // Show a "working..." message every half-second
  setTimeout(function working() {
    if ( dfd.state() === "pending" ) {
      dfd.notify( "working... " );
      setTimeout( working, 500 );
    }
  }, 1 );

  // Return the Promise so caller can't change the Deferred
  return dfd.promise();
}

// Attach a done, fail, and progress handler for the asyncEvent
$.when( asyncEvent() ).then(
  function( status ) {
    alert( status + ", things are going well" );
  },
  function( status ) {
    alert( status + ", you fail this time" );
  },
  function( status ) {
    $( "body" ).append( status );
  }
);

For more information, see the documentation for Deferred object: http://api.jquery.com/category/deferred-object/

jQuery.when()

Provides a way to execute callback functions based on one or more objects, usually Deferred objects that represent asynchronous events.Example:

$.when( $.ajax( "test.aspx" ) ).then(function( data, textStatus, jqXHR ) {
  alert( jqXHR.status ); // Alerts 200
});
like image 175
Pranav Singh Avatar answered Sep 30 '22 19:09

Pranav Singh


See Stefan's answer on using ES2015 async/await now adays.


Original Answer

You could consider asyncawait which effectively lets you write code as follows

var foo = async (function() {
    var resultA = await (firstAsyncCall());
    var resultB = await (secondAsyncCallUsing(resultA));
    var resultC = await (thirdAsyncCallUsing(resultB));
    return doSomethingWith(resultC);
});

Instead of the following

function foo2(callback) {
    firstAsyncCall(function (err, resultA) {
        if (err) { callback(err); return; }
        secondAsyncCallUsing(resultA, function (err, resultB) {
            if (err) { callback(err); return; }
            thirdAsyncCallUsing(resultB, function (err, resultC) {
                if (err) {
                    callback(err);
                } else {
                    callback(null, doSomethingWith(resultC));
                }
            });

        });
    });
}
like image 45
Jay Wick Avatar answered Sep 30 '22 21:09

Jay Wick