2013-04-18 11 views
7

Czy mogę używać jquery done() w "nie-ajaxowych" funkcjach. Otrzymuję komunikat o błędzie Uncaught TypeError: Cannot call method 'done' of undefined, gdy próbuję zrobić coś takiego.Użyj jquery wykonanej na "nie-ajaxowej" funkcji

function countThreeSeconds() { 
    var counter = 0, 
    timer = setInterval(function() { 

     if (counter == 3) { 
      console.log("All done. That was three seconds."); 
      window.clearInterval(timer); 

     } else { 
      console.log("Not there yet. Counter at: " + counter); 
     } 
     counter++; 
    }, 1000); 

} 

(function(){ 
    var timer = countThreeSeconds().done(function(){ 
    alert("done"); 
    }); 

}()); 

Dzięki

JSBIN

+3

Jak widać, nie można. jQuery nie ma z tym nic wspólnego. Nigdy nie można wywołać metody na "niezdefiniowanym". Metody jQuery nie magicznie pojawiają się wszędzie * (dzięki Bogu) *. Możesz wywoływać je na określonych obiektach zdefiniowanych w bibliotece jQuery i zgodnie z opisem interfejsu API jQuery. –

Odpowiedz

13

Bądź funkcja non-ajax zwraca obiekt obietnicy.

function countThreeSeconds() { 
    var counter = 0, 
    deferred = $.Deferred(), 
    timer = setInterval(function() { 

     if (counter == 3) { 
      console.log("All done. That was three seconds."); 
      window.clearInterval(timer); 
      deferred.resolve(); 

     } else {    
      console.log("Not there yet. Counter at: " + counter); 
      deferred.notify(counter); 
     } 
     counter++; 
    }, 1000); 
    return deferred.promise(); 

} 

(function(){ 
    var timer = countThreeSeconds().done(function(){ 
    alert("done"); 
    }).progress(function(i){ 
    console.log("in progress...",i); 
    }); 

}()); 
+0

To jest naprawdę miłe. I ma doskonały sens. Tak oczywiste, że nie mogłem oczekiwać, że normalna funkcja automatycznie uzyska dostęp do wszystkich odroczonych metod, takich jak jquery ajax. Dzięki wielkie! – 1252748

+0

Jak działa przecinek w ostatniej konsoli? Nie widziałem tego wcześniej .. – 1252748

+0

'console.log()' akceptuje nieskończoną (myślę?) Liczbę argumentów, pozwala tylko na zalogowanie się więcej niż jednej rzeczy lub etykietowanie każdego dziennika, dzięki czemu wiesz, co to jest jest. –

2

Skoro nie masz nic powracający z funkcji, to jest całkowicie poprawny zachowanie JS. Aby móc korzystać z funkcji done, zwróć obiekt jQuery.Deferred z tego obiektu.

coś takiego:

function countThreeSeconds() { 
    var defer = $.Deferred(function() { // do your stuff here }); 
    return defer.promise(); 
} 
+0

Dlaczego przekazujesz funkcję do '$ .Deferred'? To jest * nie *, gdzie znajduje się twój kod. –

+0

@RocketHazmat Nie ma nic złego w robieniu tego w funkcji. http://pastebin.com/CWXWcmkS –

+0

@KevinB: Właśnie obejrzałem dokumenty. Zgadnij, że masz rację, ale nigdy tego nie widziałem. –

0

Thomas, z czymś takim, można zrobić odroczonym obiekt (i jej obietnicy) naprawdę pracować dla Ciebie.

Na przykład można uczynić z countThreeSeconds() surową, bardziej uogólnioną funkcję i mieć wszystkie postępy/wykonane raporty wykonywane w funkcji wywołującej.

function countSeconds(n) { 
    var dfrd = $.Deferred(), 
     counter = 0, 
     timer = setInterval(function() { 
      counter++; 
      if (counter < n) { dfrd.notify(counter); } 
      else { dfrd.resolve(); } 
     }, 1000); 
    return { 
     promise: dfrd.promise(), 
     timer: timer 
    }; 
} 

(function() { 
    var timerObj = countSeconds(3); 
    timerObj.promise.progress(function(counter) { 
     console.log("Not there yet. Counter at: " + counter); 
    }).done(function() { 
     clearInterval(timerObj.timer); 
     console.log("All done. That was three seconds."); 
     alert("done"); 
    }); 
}()); 

Zatem kolejna funkcja mogłaby wywołać countSeconds() z inną wartością, a uchwyt postępów i sytuacji zrobić inaczej.

Na przykład:

(function() { 
    var timerObj = countSeconds(10); 
    timerObj.promise.progress(function(counter) { 
     $("#message").text("Counter = " + counter); 
    }).done(function() { 
     clearInterval(timerObj.timer); 
     $("#message").text('Complete'); 
    }); 
}()); 
Powiązane problemy