Bhojendra Rauniyar
Bhojendra Rauniyar

Reputation: 85545

Changing the deferred when returning it?

I've taken the following code from the docs:

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 );
  }
);

I'm very noob at understanding the deferred's promise with the line:

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

Okay, I understood we can't change the resolve or reject property of the Deferred object.

But using return dfd than return dfd.promise() caller can change the deferred object. I couldn't find in the wild. Can you please give an example (A clear concept) if I return deferred instead (just to know about it properly)?

Upvotes: 0

Views: 82

Answers (2)

guest271314
guest271314

Reputation: 1

Edit, Updated

jQuery appear to have removed exposing resolve, reject, notify, resolveWith, rejectWith, and notifyWith methods within .then at most recent version ; though still exposed at 1.7.2 http://jsfiddle.net/8mbgzrkn , http://jsfiddle.net/8mbgzrkn/1

var fn = function() {
  var dfd = new $.Deferred();
  dfd.resolve(1);
  return dfd
};

var res = fn().then(function(data) {
  console.log(data, this);
  //this.resolve(2);
  return this
});

res.then(function(deferred) {
  console.log(deferred)
});

Upvotes: 1

Kelsadita
Kelsadita

Reputation: 1038

Explanation

If you use return dfd instead of return dfd.promise(), the caller can actually change the state promise.

Means the caller can call resolve, reject, notify, resolveWith, rejectWith, and notifyWith on the returned dfd object to change the state of Deffered object.

By doing return dfd.promise() you are avoiding call from doing that. This fits for the scenario for which you don't want to change the state of Deferred object by caller function.


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;
}


// Attach a done, fail, and progress handler for the asyncEvent
$.when(asyncEvent().reject("sorry")).then(

function (status) {
    alert(status + ", things are going well");
},

function (status) {
    alert(status + ", you fail this time");
},

function (status) {
    $("body").append(status);
});

In this example, instead of returning dfd.promise() I am returning dfd object. And then I am rejecting it directly when it is called under $.when


JS Fiddle

http://jsfiddle.net/8mbgzrkn/1/


If you change the asyncEvent() function to return return dfd.promise(); and execute same code again, you will surely get an error as undefined is not a function on that line

promise error

Upvotes: 1

Related Questions