2015-07-23 14 views
10

Więc ... Meteor.defer(function(){ // stuff }) nie jest w docs:Czy ktoś może wyjaśnić, w jaki sposób działa Meteor.defer()?

https://github.com/meteor/meteor/issues/2176

Ale this linki zdaje się mówić, że jest to po prostu odpowiednikiem

Meteor.setTimeout(function(){ // stuff }, 0); 

Jeśli to przypadek, w jaki sposób to zrobić um, cokolwiek? Zasadniczo mówi "czekaj przez 0 ms, a następnie uruchom funkcję".

Tak ... natychmiast uruchamia funkcję.

Czego mi tu brakuje? Czy jest to coś w rodzaju: Tracker.afterFlush czy coś takiego? Czy w jakiś sposób czeka na "rzeczy" (jakie rzeczy?) Zakończyć przed uruchomieniem?

Odpowiedz

17

widzę Meteor.defer() dużo na SO używany jako bit hack na dodanych metod pomocniczych do uruchomienia po dom jest (nieco) załadowane - w zasadzie, aby uzyskać taki sam efekt, jak działa kod wewnątrz metody Template.foo.rendered .

Jednak głównym (i najlepszym) użyciem Meteor.defer jest uruchomienie zadania asynchronicznie.

Załóżmy, że mamy aplikację, do której wysyłamy e-mail. Na serwerze przetworzenie w metodzie meteorologicznej może zająć kilka sekund, co znacznie spowolni działanie aplikacji. Jeśli jednak zawiniesz ten proces w Meteor.defer, przetwarzanie e-maili nie zablokuje wykonania, wiadomość e-mail nadal będzie wysyłana (gdy otrzyma szansę, nie natychmiast), ale wszystko działa znacznie szybciej, ponieważ poniższy kod nie jest Czekanie. Istnieje świetny przykład lekcji na temat odradzania wykonywania na Bulletproof Meteor.

Rzeczywiście można uzyskać ten sam efekt z setTimeout(f,0) - jeśli masz wolne funkcji, można owinąć je w setTimeout i reszta kodu zakończy, a „defer” powolny proces w limit czasu, więc chociaż nie wygląda na to, setTimeout(f,0) ma naprawdę użyteczny cel!

Aby zobaczyć przykład tego działania, here's a fiddle, otwórz konsolę i obserwuj, gdzie loguje się "foo".

+0

Gotcha.Dziękuję za wyjaśnienie. Pomyślałem, że 'odroczenie' może być czymś, czego mogłem użyć, aby czekać na załadowanie elementów DOM przed zainicjowaniem kodu zewnętrznego, ponieważ ten post wspomina o tym - https://github.com/meteor/meteor/issues/2176 -:' Regularnie używam Meteor.defer(). Za każdym razem mam instrukcję w moim kodzie, która nie wydaje się wykonywać, a następnie uruchamiam tę samą instrukcję w konsoli i działa, pakuję ją w mój kod Meteor.defer() i to zwykle działa. Zazwyczaj wydaje się, że przypadki, w których coś w DOM, na którym jestem zależny, nie zostały jeszcze zrenderowane. ... ' – fuzzybabybunny

+0

Nie rozumiem, w jaki sposób można go wykorzystać do wywołania efektu" renderowanego ". Jeśli użyjesz 'odroczenia', aby utworzyć kod' asynchroniczny', tj. 'Nieblokujący', kod zostanie po prostu natychmiast wykonany bez czekania na cokolwiek ... jest to dokładnie przeciwieństwo czekania na coś do zakończenia (jak renderowanie DOM). – fuzzybabybunny

+0

To ma sens ... uruchamianie 'odroczenia' usuwa go z bieżącej kolejki wykonania, a ponieważ js jest pojedynczym wątkiem, po prostu uruchamia się, gdy kończy się cokolwiek w kolejce wykonania - tak więc działa jak część opóźnienie (w twoim pierwszym komentarzu), ale nie jest natychmiast wykonywane (ponieważ pojedynczy wątek) w twoim drugim komentarzu. –

-1

Napotkałem problem w moim projekcie z powodu asynchronicznego wywołania zwrotnego. Wewnątrz onCreated wykonałem serwer Meteor.call i ustawiłem odpowiedź wewnątrz reactiveVar. I robiłem coś wewnątrz onRendered z tym reactiveVar. Za każdym razem, gdy reactiveVar wyświetlał niezdefiniowany.

Więc użyłem Meteor.defer(function(){...}) wewnątrz onRendered i to na mój temat.

Oto demo z oraz bez stosowania Meteor.defer()

Template.myTemplate.onCreated(function() { 
    var instance = this; 
    instance.myTemplateModel = new ReactiveDict(); 

    Meteor.call('all-user', function(err, res){ 
     if(res){ 
      console.log('inside callback'); 
      instance.myTemplateModel.set('users', res); 
     } 
    }); 
}); 

Template.myTemplate.onRendered(function() { 
    var instance = this 
    console.log('rendered start'); 
    Meteor.defer(function(){ 
     console.log(instance.myTemplateModel.get('users')); 
    }); 
    console.log('render end'); 
}); 

Console:

/*Without Meteor.defer()*/   | /*With Meteor.defer()*/ 
render start      | inside callback 
undefined       | render start 
render end       | render end 
inside callback     | [Object, Object, Object] 
+1

Przyjmuję również, że jest to jeden z najlepszych sposobów rozwiązania tego rodzaju problemu asynchronicznego wykonywania, mam nadzieję, że może to pomóc innym. a także daj nam znać, czy istnieją inne możliwe sposoby ... szczęśliwe kodowanie. :) – iamhimadri

+1

-1 To jest proszenie o kłopoty ... Po prostu masz szczęście, że twoje wywołanie metody działa wystarczająco szybko (jestem pewna, że ​​ma skrót). Nie ma żadnej możliwości upewnienia się, że funkcja odkładania zostanie wywołana po wywołaniu metody. Ta funkcja zostanie uruchomiona po wykonaniu wszystkich aktualnie planowanych wykonań. Oddzwanianie nie zostanie zaplanowane, jeśli czekasz na odpowiedź z serwera, tak jak sugerujesz. – Salketer

Powiązane problemy