Zrozumienie obietnic w Node.js.

147

Z tego, co zrozumiałem, istnieją trzy sposoby wywoływania kodu asynchronicznego:

  1. Wydarzenia, np request.on("event", callback);
  2. Callback, np fs.open(path, flags, mode, callback);
  3. Obietnice

Znalazłem bibliotekę z obietnicą węzłów, ale jej nie rozumiem.

Czy ktoś mógłby wyjaśnić, o co chodzi w obietnicach i dlaczego powinienem ich używać?

Dlaczego został usunięty z Node.js?

ajsie
źródło
Ten artykuł dość dobrze to wyjaśnia. Jeśli chodzi o implementację, którą można wykorzystać w node.js, spójrz na Futures
Sean Kinsey
Oto świetna seria, której użyłem do stworzenia mojej własnej klasy obietnicy: Let's Make a Framework: Promises Oto film o jQuery Deferred
Tom Winter

Odpowiedzi:

91

Obietnice w node.js obiecywały wykonanie jakiejś pracy, a następnie miały oddzielne wywołania zwrotne, które byłyby wykonywane w przypadku sukcesu i niepowodzenia, a także obsługi limitów czasu. Innym sposobem myślenia o obietnicach w node.js było to, że były to emitery, które mogły emitować tylko dwa zdarzenia: sukces i błąd.

Fajną rzeczą w obietnicach jest to, że można je łączyć w łańcuchy zależności (obietnice C należy wykonywać tylko po ukończeniu Obietnic A i Obietnic B).

Usuwając je z rdzenia node.js, stworzył możliwość budowania modułów z różnymi implementacjami obietnic, które mogą znajdować się na szczycie rdzenia. Niektóre z nich to obietnica węzłów i przyszłość .

Paul Robinson
źródło
10
@weng Nie, nie jest.
Ivo Wetzel
98

Ponieważ to pytanie wciąż ma wiele poglądów (takich jak moje), chciałem zwrócić uwagę, że:

  1. node-obietnica wydaje mi się raczej martwa (ostatnie zatwierdzenie miało miejsce około 1 rok temu) i prawie nie zawiera testów.
  2. Te kontrakty moduł wygląda bardzo nadęty do mnie i jest źle udokumentowane (i myślę, że konwencje nazewnictwa są po prostu złe)
  3. Wydaje się, że najlepszą drogą jest framework q , który jest zarówno aktywny, jak i dobrze udokumentowany.
enyo
źródło
9
Sprawdź też ten github.com/medikoo/deferred , Q jest jednym z pierwszych i zdecydowanie jest inspiracją dla wielu wdrożeń, które pojawiły się później, ale niestety jest bardzo powolne i zbyt „teoretyczne” w niektórych miejscach, z niektórymi nie gra dobrze scenariusze ze świata rzeczywistego
Mariusz Nowak
Obejrzałbym ten film na temat obietnic jednego z twórców RSVP.js youtube.com/…
runspired
23
Aktualizacja 2014 - bluebird jest obecnie zdecydowanie najszybszym i jednym z najlepszymi możliwościami debugowania.
Benjamin Gruenbaum
19

Obietnica to „rzecz”, która reprezentuje „ostateczne” rezultaty operacji, że tak powiem. Należy tu zauważyć, że usuwa szczegóły, kiedy coś się dzieje i pozwala skupić się na tym, co powinno się wydarzyć po tym, jak coś się wydarzy. Spowoduje to czysty, możliwy do utrzymania kod, w którym zamiast wywołania zwrotnego w wywołaniu zwrotnym wewnątrz wywołania zwrotnego, Twój kod będzie wyglądał mniej więcej tak:

 var request = new Promise(function(resolve, reject) {
   //do an ajax call here. or a database request or whatever.
   //depending on its results, either call resolve(value) or reject(error)
   //where value is the thing which the operation's successful execution returns and
   //error is the thing which the operation's failure returns.
 });

 request.then(function successHandler(result) {
   //do something with the result
 }, function failureHandler(error) {
  //handle
 });

Specyfikacja obietnic mówi, że obietnica jest

then

metoda powinna zwrócić nową obietnicę, która jest spełniona, gdy dane wywołanie zwrotne successHandler lub failureHandler zostanie zakończone. Oznacza to, że możesz łączyć obietnice w łańcuchy, gdy masz zestaw asynchronicznych zadań, które należy wykonać, i mieć pewność, że sekwencjonowanie operacji jest gwarantowane tak, jakbyś używał wywołań zwrotnych. Więc zamiast przekazywać wywołanie zwrotne w wywołaniu zwrotnym w wywołaniu zwrotnym, kod z powiązanymi obietnicami wygląda następująco:

var doStuff = firstAsyncFunction(url) {
                return new Promise(function(resolve, reject) {
                       $.ajax({
                        url: url,
                        success: function(data) {
                            resolve(data);
                        },
                        error: function(err) {
                             reject(err); 
                        } 
                  });
               };
doStuff
  .then(secondAsyncFunction) //returns a promise
  .then(thirdAsyncFunction); //returns a promise

Aby dowiedzieć się więcej o obietnicach i dlaczego są super fajne, odwiedź blog Domenica: http://domenic.me/2012/10/14/youre-missing-the-point-of-promises/

Hrishi
źródło
12

Ten nowy samouczek na temat Promises od autora PouchDB jest prawdopodobnie najlepszym, jaki kiedykolwiek widziałem. Mądrze obejmuje klasyczne błędy debiutanta, pokazując prawidłowe wzorce użycia, a nawet kilka anty-wzorców, które są nadal powszechnie używane - nawet w innych samouczkach !!

Cieszyć się!

PS Nie odpowiedziałem na inne części tego pytania, ponieważ zostały one dobrze omówione przez innych.

Tony O'Hagan
źródło
Moje jedyne przeprosiny za to to zmuszanie cię do czytania humoru pod koniec błędu nr 4 Zaawansowanego.
Tony O'Hagan
W rzeczywistości kod w samouczku, który twierdzi, że jest antywzorem, wymaga zagnieżdżenia dla pętli i warunku, i nie może być tak łatwo spłaszczony, jak sugerują.
Bergi
Zaawansowany błąd nr 4 można również rozwiązać przy użyciu znacznie większej liczby różnych podejść, zobacz Jak uzyskać dostęp do poprzednich wyników obietnic w łańcuchu .then ()? ( sugerowany przez nich wzór zamknięcia nie wydaje się być zbyt popularny).
Bergi
Myślę, że ta odpowiedź zawierająca tylko łącze powinna była być komentarzem. W swojej odpowiedzi podaj przynajmniej główne punkty tego artykułu.
Bergi
7

Mike Taulty ma serię filmów , z których każdy zajmuje mniej niż dziesięć minut, opisujących sposób działania biblioteki WinJS Promise.

Te filmy są dość pouczające, a Mike'owi udaje się pokazać moc Promise API za pomocą kilku dobrze dobranych przykładów kodu.

var twitterUrl = "http://search.twitter.com/search.json?q=windows";
var promise = WinJS.xhr({ url: twitterUrl });

 promise = promise.then(
     function (xhr) {
     },
     function (xhr) {
         // handle error
     });

Sposób traktowania wyjątków jest szczególnie dobry.

Pomimo odniesień do WinJs, jest to seria filmów o ogólnym zainteresowaniu, ponieważ Promise API jest zasadniczo podobny w wielu jego implementacjach.

RSVP to lekka implementacja Promise, która przechodzi pomyślnie zestaw testów Promise / A +. Bardzo podoba mi się interfejs API, ponieważ jest podobny stylem do interfejsu WinJS.

Aktualizacja kwiecień 2014

Nawiasem mówiąc, biblioteka WinJS jest teraz open source .

Noel Abrahams
źródło
1
+1. To pierwszy przykład, jaki widziałem, który ma dla mnie sens i jest intuicyjny w użyciu. W jakiś sposób mój mózg nie może przeanalizować wszystkich predefiniowanych parametrów deferredsi resolvei deferred.promise.theni promiseActionsw popularnej dokumentacji biblioteki Q. Czy jest szansa, że ​​znasz coś tak prostego dla Node.js ?
Redsandro
1
@noel dziękuję za udostępnienie powyższego linku, jest to doskonała seria wprowadzająca do obietnic i zgadzam się, że specyfika WinJS nie ma znaczenia, ponieważ ogólne podejście / temat jest uniwersalny.
arcseldon
Niezły przykład.
Poprawiłem
5

Kolejną zaletą obietnic jest to, że obsługa błędów oraz zgłaszanie i przechwytywanie wyjątków jest znacznie lepsza niż próba obsłużenia tego za pomocą wywołań zwrotnych.

The Bluebird biblioteka implementuje obietnice i daje wielkie ślady długo stos, jest bardzo szybki, i ostrzega o błędach Uncaught. Jest również szybszy i zużywa mniej pamięci niż inne biblioteki obiecujące, zgodnie z http://bluebirdjs.com/docs/benchmarks.html

llambda
źródło
4

Czym dokładnie jest obietnica?

Obietnica to po prostu obiekt, który reprezentuje wynik operacji asynchronicznej. Obietnica może mieć dowolny z trzech następujących stanów:

w toku :: To jest stan początkowy, co oznacza, że ​​obietnica nie została spełniona ani odrzucona.

spełnione : Oznacza to, że obietnica została spełniona, oznacza to, że wartość, którą reprezentuje obietnica, jest gotowa do użycia.

odrzucone :: Oznacza to, że operacje się nie powiodły i dlatego nie mogą spełnić obietnicy. Oprócz państw istnieją trzy ważne podmioty związane z obietnicami, które naprawdę musimy zrozumieć

  1. executor function :: executor function definiuje operację asynchroniczną, która ma zostać wykonana i której wynik jest reprezentowany przez obietnicę. Rozpoczyna się wykonywanie zaraz po zainicjowaniu obiektu obietnicy.

  2. olve :: solution to parametry przekazane do funkcji wykonawczej, aw przypadku pomyślnego uruchomienia modułu wykonawczego to rozwiązanie jest nazywane przekazaniem wyniku.

  3. odrzucanie :: odrzucanie to kolejny parametr przekazywany do funkcji executora i jest on używany, gdy funkcja executora zawodzi. Przyczyna niepowodzenia może zostać przekazana odrzuceniu.

Więc za każdym razem, gdy tworzymy obiekt obietnicy, musimy zapewnić wykonanie, rozwiązanie i odrzucenie.

Odniesienie :: Obietnice

Rishabh.IO
źródło
0

Ostatnio przyglądałem się również obietnicom w node.js. Do tej pory wydawało się, że when.js jest właściwą drogą ze względu na szybkość i wykorzystanie zasobów, ale dokumentacja dotycząca q.js dała mi dużo lepsze zrozumienie. Więc użyj when.js, ale q.js docs, aby zrozumieć temat.

Z pliku q.js readme na github:

Jeśli funkcja nie może zwrócić wartości lub zgłosić wyjątku bez blokowania, może zamiast tego zwrócić obietnicę. Obietnica to obiekt, który reprezentuje wartość zwracaną lub zgłoszony wyjątek, który funkcja może ostatecznie dostarczyć. Obietnica może być również używana jako proxy dla zdalnego obiektu w celu pokonania opóźnienia.

Andrew Roberts
źródło
0

Obiekt Promise reprezentuje zakończenie lub niepowodzenie operacji asynchronicznej.

Aby zrealizować obietnicę, potrzebujesz dwóch części: -

1. Tworzenie obietnicy:

Konstruktor obietnicy akceptuje funkcję zwaną executorem, która ma 2 parametry, rozwiązuj i odrzucaj.

function example(){
   return new Promise (function(resolve , reject){   //return promise object
      if(success){
         resolve('success');  //onFullfiled
      }else{
         reject('error');     //onRejected
      }
   })
}

2. Obietnica obsługi:

Obiekt Promise ma 3 metody obsługi obiektów Promise: -

1.Promise.prototype.catch (onRejected)

2.Promise.prototype.then (onFullfiled)

3.Promise.prototype.finally (onFullfiled, onRejected)

example.then((data) =>{
  //handles resolved data
  console.log(data); //prints success     
}).catch((err) => {
  //handles rejected error 
  console.log(err);  //prints error
})
Pavneet Kaur
źródło