-1

i am trying to learn jQuery deferred and implement it in my code.

function function1() {
  $deferred = $.Deferred();
  setTimeout(function() {
    alert("Hello");
  }, 3000);
  return $deferred.promise();
}

function function2() {
  alert('done');
}
$("button").click(function() {
  function1().done(function2());
});

I have a simple functions function1 and function2, i want the function2 to be called after execution of function1, but I am not able to get the result. can anyone point me what exactly am i doing wrong.

I am using jquery-1.10.js as my version

Thank you.

BenG
  • 14,826
  • 5
  • 45
  • 60
Lijin Durairaj
  • 4,910
  • 15
  • 52
  • 85
  • 1
    Why are you using such an old version of jQuery? Even if you want to retain very old browser compatibility, you could at least use the latest 1.x version. – jfriend00 Jul 15 '16 at 21:00

2 Answers2

3

You're pretty close.

You need to resolve your promise and use .then:-

function function1() {
   $deferred = $.Deferred();
   setTimeout(function() {
     alert("Hello");
     $deferred.resolve();
   }, 3000);
   return $deferred.promise();
 }

 function function2() {
   alert('done');
 }
 $("button").click(function() {
   function1().then(function2);
 });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<button>call</button>
BenG
  • 14,826
  • 5
  • 45
  • 60
  • 1
    Uhh, there's no reason to use `$.when()` here, in fact it's wasteful and wrong to recommend it. You can just do `function1().then(...)` directly. Also, I'd strongly recommend using the ES6 standard `.then()` rather than the jQuery proprietary `.done()`. There is an important difference in behavior between the two in jQuery 3.x as jQuery has made `.then()` more compatible with the ES6 promise standard. – jfriend00 Jul 15 '16 at 20:16
2

You have a couple problems:

  1. You were never resolving your deferred. You have to call def.resolve() for it to notify the promise listeners that the promise is now resolved.
  2. function1().done(function2()); needs to be function1().done(function2);. When you have the parens after function2() that tells the JS interpreter to call the function immediately and pass the return value which is undefined. Without the parens passes a reference to the function as a .done() handler so the promise infrastructure can call it later (that's what you want).

I'd suggest the following code:

function function1() {
    return $.Deferred(function(def) {
        console.log("start of function1");
        setTimeout(function() {
            console.log("timer fired");
            def.resolve();
        }, 3000);
    }).promise();
}

function function2() {
  console.log('done');
}
$("button").click(function() {
    function1().then(function2);
});

In addition to fixing the above issues, this also changes:

  1. It uses the deferred constructor. This saves some code (uses fewer intermediaries) and is more compatible with the ES6 promise specification and supported by jQuery.
  2. It uses .then() instead of the jQuery-proprietary .done() which is more compatible with the ES6 promise specification and supported by jQuery.

I'd also suggest that you upgrade to a newer release of jQuery as 1.10 is already 3+ years old by now. If you absolutely have to maintain compatibility with older versions of IE, you can at least use 1.12.4.

jfriend00
  • 683,504
  • 96
  • 985
  • 979