Chcę pracować z obietnicami, ale mam interfejs API wywołania zwrotnego w formacie:
1. Ładowanie DOM lub inne jednorazowe zdarzenie:
window.onload; // set to callback
...
window.onload = function() {
};
2. Zwykły oddzwonienie:
function request(onChangeHandler) {
...
}
request(function() {
// change happened
...
});
3. Oddzwanianie w stylu węzła („nodeback”):
function getStuff(dat, callback) {
...
}
getStuff("dataParam", function(err, data) {
...
})
4. Cała biblioteka z wywołaniami zwrotnymi w stylu węzła:
API;
API.one(function(err, data) {
API.two(function(err, data2) {
API.three(function(err, data3) {
...
});
});
});
new Promise
dodatkowego znaczącego narzutu? Chcę zawinąć wszystkie moje synchroniczne funkcje Noje.js w obietnicę, aby usunąć cały kod synchroniczny z mojej aplikacji Node, ale czy to najlepsza praktyka? Innymi słowy, funkcja, która akceptuje argument statyczny (np. Ciąg znaków) i zwraca wynik obliczony, czy mam zawinąć to w obietnicę? ... Przeczytałem gdzieś, że nie powinieneś mieć żadnego kodu synchronicznego w Nodejs.Odpowiedzi:
Obietnice mają swój stan, zaczynają się jako oczekujące i mogą ustąpić:
Funkcje obiecujące powracające funkcje nigdy nie powinny rzucać , zamiast tego powinny zwracać odrzucenia. Wyrzucenie z funkcji powrotu obietnicy zmusi cię do użycia zarówno a, jak
} catch {
i a.catch
. Osoby korzystające z obiecanych interfejsów API nie oczekują, że obietnice zostaną rzucone. Jeśli nie masz pewności, jak działają asynchroniczne interfejsy API w JS - zapoznaj się z tą odpowiedzią najpierw .1. Ładowanie DOM lub inne jednorazowe zdarzenie:
Tak więc tworzenie obietnic zazwyczaj oznacza określenie, kiedy się rozliczają - to znaczy, kiedy przechodzą do fazy spełnionej lub odrzuconej, aby wskazać, że dane są dostępne (i można uzyskać do nich dostęp
.then
).Dzięki nowoczesnym implementacjom obietnic, które wspierają
Promise
konstruktora, podobnie jak natywne obietnice ES6:Następnie skorzystasz z wynikowej obietnicy w następujący sposób:
Z bibliotekami, które obsługują odroczenie (w tym przykładzie użyjemy $ q, ale jQuery użyjemy później):
Lub za pomocą interfejsu jQuery, takiego jak interfejs API, umożliwiając jednokrotne zdarzenie:
2. Zwykły oddzwonienie:
Te interfejsy API są dość powszechne, ponieważ dobrze… wywołania zwrotne są częste w JS. Spójrzmy na typowy przypadek posiadania
onSuccess
ionFail
:Dzięki nowoczesnym implementacjom obietnic, które wspierają
Promise
konstruktora, podobnie jak natywne obietnice ES6:Z bibliotekami, które obsługują odroczenie (użyjmy tutaj jQuery dla tego przykładu, ale użyliśmy również $ q powyżej):
jQuery oferuje również
$.Deferred(fn)
formularz, który ma tę zaletę, że pozwala nam napisać wyrażenie, które bardzo dokładnie emulujenew Promise(fn)
formularz, w następujący sposób:Uwaga: W tym miejscu wykorzystujemy fakt, że odroczone
resolve
ireject
metody jQuery są „odłączalne”; to znaczy. są powiązane z instancją jQuery.Deferred (). Nie wszystkie biblioteki oferują tę funkcję.3. Oddzwanianie w stylu węzła („nodeback”):
Odwołania zwrotne w stylu węzła (nodebacks) mają określony format, w którym wywołania zwrotne są zawsze ostatnim argumentem, a jego pierwszym parametrem jest błąd. Obiecajmy najpierw ręcznie:
Do:
W przypadku odroczenia możesz wykonać następujące czynności (użyjmy Q w tym przykładzie, chociaż Q obsługuje teraz nową składnię, którą powinieneś preferować ):
Ogólnie rzecz biorąc, nie powinieneś zbytnio obiecywać rzeczy, większość bibliotek obietnic, które zostały zaprojektowane z myślą o Węzle, a także natywne obietnice w Node 8+ mają wbudowaną metodę obiecujących plecaków węzłów. Na przykład
4. Cała biblioteka z wywołaniami zwrotnymi w stylu węzła:
Nie ma tutaj złotej reguły, obiecasz je jeden po drugim. Jednak niektóre implementacje obietnicy pozwalają to zrobić zbiorczo, na przykład w Bluebird, konwersja interfejsu API nodeback do interfejsu API obietnicy jest tak prosta, jak:
Lub z rodzimymi obietnicami w węźle :
Uwagi:
.then
, nie musisz obiecywać rzeczy. Zwrócenie obietnicy od.then
opiekuna rozwiązuje lub odrzuca wartość tej obietnicy. Rzucanie od przewodnika.then
jest również dobrą praktyką i odrzuca obietnicę - jest to słynne obietnica bezpieczeństwa rzucania.onload
powinieneś użyćaddEventListener
zamiastonX
.źródło
resolve()
ireject()
są zapisywane do wielokrotnego użytku, zaryzykuję, że mój zaproponował edycji jest istotne, ponieważ oferuje przykład jQuery formularza$.Deferred(fn)
, który w przeciwnym razie brakuje. Jeśli podany jest tylko jeden przykład jQuery, sugeruję, że powinien on mieć taką formę, a nievar d = $.Deferred();
itp., Ponieważ należy zachęcać ludzi do używania często zaniedbanej$.Deferred(fn)
formy, a także w takiej odpowiedzi stawia jQuery bardziej na równi z biblioteki, które używają Revealing Constructor Pattern .$.Deferred(fn)
, jeśli edytujesz to zamiast w istniejącym przykładzie w ciągu następnych 15 minut, jestem pewien, że mogę spróbować zatwierdzić go na czas :)util.promisify
, że Node.js zamierza dodać do swojego rdzenia, począwszy od wersji RC 8.0.0. Jego działanie nie różni się zbytnio od BluebirdPromise.promisify
, ale ma tę zaletę, że nie wymaga dodatkowych zależności, na wypadek, gdybyś chciał tylko natywną obietnicę. Napisałem post na blogu o util.promisify dla każdego, kto chce przeczytać więcej na ten temat.Dziś mogę użyć
Promise
wNode.js
postaci zwykłego metodą Javascript.Prosty i podstawowy przykład
Promise
(z metodą KISS ):Zwykły kod JavaScript Async API:
Promise
Kod JavaScript Async API:(Polecam odwiedzić to piękne źródło )
Również
Promise
można stosować łączneasync\await
sięES7
, aby czekać przepływu programu nafullfiled
skutek tak:Kolejne użycie z tym samym kodem przy użyciu
.then()
metodyPromise
może być również używany na dowolnej platformie, która jest oparta na node.js podobnegoreact-native
.Premia : Metoda hybrydowa
(zakłada się, że metoda wywołania zwrotnego ma dwa parametry jako błąd i wynik)
Powyższa metoda może odpowiedzieć na wyniki w przypadku zwrotów w starym stylu i obietnic.
Mam nadzieję że to pomoże.
źródło
Przed konwersją funkcji jako obietnicy w Node.JS
Po konwersji
Musisz obsłużyć wiele wniosków
źródło
Nie sądzę, aby
window.onload
sugestia @Benjamin działała cały czas, ponieważ nie wykrywa, czy zostanie wywołana po załadowaniu. Byłem przez to ugryziony wiele razy. Oto wersja, która zawsze powinna działać:źródło
setTimeout(resolve, 0)
(lubsetImmediate
, jeśli jest dostępny), aby upewnić się, że jest wywoływany asynchronicznie?resolve
synchroniczne jest w porządku. Procedury obsługi obietnicythen
są gwarantowane przez strukturę, która ma być wywoływana asynchronicznie , niezależnie od tego, czyresolve
jest wywoływana synchronicznie.Node.js 8.0.0 zawiera nowy
util.promisify()
interfejs API, który umożliwia pakowanie standardowych interfejsów API stylu wywołania zwrotnego Node.js w funkcję zwracającą obietnicę. Przykładowe zastosowanieutil.promisify()
pokazano poniżej.Zobacz Ulepszone wsparcie dla obietnic
źródło
W wersji Release Candidate dla Node.js 8.0.0 pojawiło się nowe narzędzie
util.promisify
(pisałem o util.promisify ), które zawiera w sobie zdolność obiecania dowolnej funkcji.Nie różni się zbytnio od podejść sugerowanych w innych odpowiedziach, ale ma tę zaletę, że jest podstawową metodą i nie wymaga dodatkowych zależności.
Następnie masz
readFile
metodę, która zwraca natywnąPromise
.źródło
util.promisify
dwa razy (w 2014 r., Kiedy to pytanie zostało napisane, i kilka miesięcy temu - o co nalegałem jako główny członek Node i jest to bieżąca wersja, którą mamy w Node). Ponieważ nie jest jeszcze publicznie dostępny - nie dodałem go jeszcze do tej odpowiedzi. Bylibyśmy bardzo wdzięczni za opinie na temat użytkowania i poznawanie niektórych pułapek, aby mieć lepsze dokumenty do wydania :)util.promisify
w swoim wpisie na blogu :)util.promisify.custom
symbolu można zastąpić wynik funkcji util.promisify? Szczerze mówiąc, była to celowa chybienie, ponieważ nie jestem jeszcze w stanie znaleźć przydatnego przypadku użycia. Może mógłbyś podać mi jakieś dane?fs.exists
lub interfejsy API, które nie są zgodne z konwencją dotyczącą węzłów - bluebirdPromise.promisify
popełni je źle, aleutil.promisify
poprawi je.Z Node JS możesz korzystać z natywnych obietnic JavaScript.
Link do kodu My Cloud 9: https://ide.c9.io/adx2803/native-promises-in-node
źródło
W zwykłym starym javaScript waniliowym oto rozwiązanie, które obiecuje wywołanie zwrotne interfejsu API.
źródło
Biblioteka Q firmy kriskowal zawiera funkcje zwrotne do obietnicy. Metoda taka jak ta:
można przekonwertować za pomocą Q.ninvoke
źródło
Q.denodeify
. Czy musimy podkreślać pomocników biblioteki?Jeśli masz kilka funkcji, które odbierają połączenie zwrotne i chcesz, aby zwróciły obietnicę, możesz użyć tej funkcji do konwersji.
źródło
W węźle v7.6 +, który ma wbudowane obietnice i asynchronizuje:
Jak używać:
źródło
W Node.js 8 możesz obiecać metody obiektowe w locie za pomocą tego modułu npm:
https://www.npmjs.com/package/doasync
Wykorzystuje util.promisify i proxy , aby twoje obiekty pozostały niezmienione. Zapamiętywanie odbywa się również przy użyciu WeakMaps). Oto kilka przykładów:
Z obiektami:
Z funkcjami:
Możesz nawet użyć natywnego
call
iapply
powiązać jakiś kontekst:źródło
Możesz użyć natywnej obietnicy w ES6, na przykład w przypadku setTimeout:
W tym przykładzie Obietnica nie ma powodu, by zawieść, więc
reject()
nigdy nie jest nazywana.źródło
Funkcja stylu wywołania zwrotnego jest zawsze taka (prawie wszystkie funkcje w node.js to ten styl):
Ten styl ma tę samą funkcję:
funkcja zwrotna jest przekazywana przez ostatni argument.
funkcja zwrotna zawsze przyjmuje obiekt błędu jako pierwszy argument.
Możesz napisać funkcję do konwersji funkcji w tym stylu:
Dla większej zwięzłości powyższy przykład wykorzystał ramda.js. Ramda.js to doskonała biblioteka do programowania funkcjonalnego. W powyższym kodzie użyliśmy go: zastosuj (jak javascript
function.prototype.apply
) i dopisz (jak javascriptfunction.prototype.push
). Możemy więc teraz przekonwertować funkcję stylu wywołania zwrotnego na funkcję stylu obietnicy:Funkcja toPromise i checkErr jest własnością biblioteki berserk , jest to funkcjonalny rozwidlenie biblioteki programowania autorstwa ramda.js (utworzone przeze mnie).
Mam nadzieję, że ta odpowiedź będzie dla Ciebie przydatna.
źródło
Możesz zrobić coś takiego
Następnie użyj go
źródło
es6-promisify
konwertuje funkcje oparte na wywołaniu zwrotnym na funkcje oparte na obietnicy.Patrz: https://www.npmjs.com/package/es6-promisify
źródło
Moja wersja promisify
callback
funkcji toP
funkcja:Ta
P
funkcja wymaga podpisu wywołania zwrotnegocallback(error,result)
.źródło
util.promisify(fn)
(err, value) => ...
lub musisz zdefiniować podpis niestandardowy (zobacz Niestandardowe funkcje obiecane). Dziękuję, dobra catcha.var P = function (fn, ...args) { return new Promise((resolve, reject) => fn.call(this, ...args, (error, result) => error ? reject(error) : resolve(result))); };
zrobiłby to samo co twoje i jest o wiele prostsze.Poniżej przedstawiono implementację sposobu, w jaki funkcja (API zwrotne) może zostać przekonwertowana na obietnicę.
źródło
To jest jak 5 lat spóźnienia, ale chciałem opublikować tutaj moją wersję promesify, która przejmuje funkcje z API zwrotnego i zamienia je w obietnice
Zobacz tę bardzo prostą wersję tutaj: https://gist.github.com/jdtorregrosas/aeee96dd07558a5d18db1ff02f31e21a
źródło