Korzystam z ES6 Promise.
Zwykle obietnica jest budowana i używana w ten sposób
new Promise(function(resolve, reject){
if (someCondition){
resolve();
} else {
reject();
}
});
Ale robiłem coś takiego, jak poniżej, aby podjąć decyzję na zewnątrz ze względu na elastyczność.
var outsideResolve;
var outsideReject;
new Promise(function(resolve, reject) {
outsideResolve = resolve;
outsideReject = reject;
});
I później
onClick = function(){
outsideResolve();
}
Działa to dobrze, ale czy jest na to łatwiejszy sposób? Jeśli nie, czy to dobra praktyka?
javascript
promise
es6-promise
Morio
źródło
źródło
Promise
musi być wykonywane synchronicznie, aby umożliwić „eksportowanie” dwóch funkcji.Odpowiedzi:
Nie, nie ma innego sposobu, aby to zrobić - jedyne, co mogę powiedzieć, to to, że ten przypadek użycia nie jest zbyt powszechny. Jak powiedział Felix w komentarzu - to, co robisz, będzie konsekwentnie działać.
Warto wspomnieć, że powodem, dla którego konstruktor obietnicy zachowuje się w ten sposób, jest bezpieczeństwo rzucania - jeśli wyjątek, którego się nie spodziewałeś, zdarzy się, gdy Twój kod działa wewnątrz konstruktora obietnicy, zmieni się w odrzucenie, ta forma bezpieczeństwa rzucania - konwertuje zgłoszone błędy na odrzucenia są ważne i pomagają utrzymać przewidywalny kod.
Z tego powodu rzutu bezpieczeństwa wybrano konstruktora obietnicy zamiast odroczenia (które są alternatywnym sposobem budowania obietnicy, który pozwala na to, co robisz) - tak jak w przypadku najlepszych praktyk - przekazałbym element i zamiast tego użyłem konstruktora obietnicy:
Z tego powodu - w dowolnym momencie można użyć konstruktora obietnica na eksporcie funkcje - polecam zrobić z niego korzystać. Ilekroć możesz uniknąć obu - unikaj obu i łańcucha.
Zauważ, że nigdy nie powinieneś używać konstruktora obietnic do takich rzeczy
if(condition)
, pierwszy przykład można zapisać jako:źródło
Promise
łańcuch? Np. W moim szczególnym przypadku jestem na serwerze i czekam na konkretną odpowiedź klienta (uścisk dłoni typu SYN-ACK, aby upewnić się, że klient pomyślnie zaktualizował stan).prosty:
źródło
promiseResolve()
. Semantyka obietnicy polega na tym, że zawsze zwraca wartość. Jest to również funkcjonalnie takie samo jak post OP, nie rozumiem, jaki problem rozwiązuje w sposób wielokrotnego użytku.promiseResolve()
, nie zgłosi wyjątku. Możesz zdefiniować a.catch
na konstruktorze i bez względu na to, jaki kod go.catch
wywoła, wywołane zostaną konstruktory . Oto jsbin pokazujący, jak to działa: jsbin.com/yicerewivo/edit?js,consoleTrochę za późno na przyjęcie tutaj, ale innym sposobem na to byłoby użycie Odroczonego obiektu. Zasadniczo masz taką samą ilość płyty kotłowej, ale jest to przydatne, jeśli chcesz je przekazać i ewentualnie rozwiązać poza ich definicją.
Naiwne wdrożenie:
Wersja ES5:
źródło
resolve|reject
przypisuje się je leksykalnie, czy poprzezbind
. To tylko prosta implementacja obiektu jQuery Deferred, który istnieje od 1.0 (ish). Działa dokładnie jak obietnica, z tym wyjątkiem, że nie ma bezpieczeństwa rzucania. Istotą tego pytania było, jak zapisać kilka wierszy kodu podczas tworzenia obietnic.Deferred
przestarzałe?Rozwiązanie, które wymyśliłem w 2015 roku dla mojego frameworka. Ten rodzaj obietnic nazwałem Zadaniem
źródło
Podobała mi się odpowiedź @JonJaques, ale chciałem pójść o krok dalej.
Jeśli powiążesz,
then
acatch
następnieDeferred
obiekt, to w pełni implementujePromise
interfejs API i możesz traktować go jako obietnicęawait
i tak dalej.źródło
Metoda pomocnicza złagodziłaby ten dodatkowy koszt i dałaby ci to samo wrażenie jQuery.
Wykorzystanie byłoby
Który jest podobny do jQuery
Chociaż w przypadku użycia ta prosta, natywna składnia jest w porządku
źródło
Korzystam z funkcji pomocnika, aby utworzyć coś, co nazywam „płaską obietnicą” -
I używam tego tak -
Zobacz pełny przykład działania -
Pokaż fragment kodu
Edycja: Utworzyłem pakiet NPM o nazwie Flat-Promise, a kod jest również dostępny na GitHub .
źródło
Możesz zawrzeć Obietnicę w klasie.
źródło
Wiele odpowiedzi tutaj jest podobnych do ostatniego przykładu w tym artykule . Buforuję wiele obietnic, a funkcje
resolve()
ireject()
można przypisać do dowolnej zmiennej lub właściwości. W rezultacie jestem w stanie uczynić ten kod nieco bardziej kompaktowym:Oto uproszczony przykład użycia tej wersji
defer()
połączeniaFontFace
Obietnicy obciążenia z innym procesem asynchronicznym:Zaktualizuj: 2 alternatywy na wypadek, gdybyś chciał obudować obiekt:
i
źródło
const result = await deferred.promise;
Zaakceptowana odpowiedź jest nieprawidłowa. Korzystanie z zakresu i odniesień jest dość łatwe, chociaż może oburzyć purystów Obiecujących:
Zasadniczo chwytamy odniesienie do funkcji rozstrzygania, gdy obietnica jest tworzona, i zwracamy ją, aby można ją było ustawić zewnętrznie.
W ciągu jednej sekundy konsola wyśle:
źródło
Tak, możesz. Korzystając z
CustomEvent
interfejsu API dla środowiska przeglądarki. I za pomocą projektu emitera zdarzeń w środowiskach node.js. Ponieważ fragment kodu w pytaniu dotyczy środowiska przeglądarki, oto działający przykład tego samego.Mam nadzieję, że ta odpowiedź będzie przydatna!
źródło
Naszym rozwiązaniem było użycie zamknięć do przechowywania funkcji rozstrzygania / odrzucania oraz dodatkowo dołączanie funkcji przedłużającej samą obietnicę.
Oto wzór:
I używając go:
źródło
promise.resolve_ex = _resolve; promise.reject_ex = _reject;
... nadal działa dobrze.W niektórych przypadkach brakuje mi również odroczonego wzoru. Zawsze możesz utworzyć jeden na obietnicy ES6:
źródło
Dziękujemy wszystkim, którzy opublikowali ten wątek. Utworzyłem moduł, który zawiera opisany wcześniej obiekt Defer (), a także kilka innych zbudowanych na nim obiektów. Wszystkie wykorzystują obietnice i zgrabną składnię oddzwaniania Promise do implementacji komunikacji / obsługi zdarzeń w programie.
Kolejka: kolejka wykonania oparta na łańcuchach Promise.
rp = require("repeatable-promise")
https://github.com/CABrouwers/repeatable-promise
źródło
Napisałem za to małą bibliotekę. https://www.npmjs.com/package/@inf3rno/promise.exposed
Kiedyś podejście metoda fabryki inni napisał, ale overrode
then
,catch
,finally
metody też, więc można rozwiązać oryginalnego obietnicy przez tych, jak również.Rozwiązanie Obietnicy bez wykonawcy z zewnątrz:
Wyścigi z setem egzekutora Timeout z zewnątrz:
Istnieje tryb bez konfliktu, jeśli nie chcesz zanieczyszczać globalnej przestrzeni nazw:
źródło
Stworzyłem bibliotekę o
manual-promise
tej nazwie, która zastępujePromise
. Żadna z pozostałych odpowiedzi tutaj nie będzie działać jako drop w zastępstwie dlaPromise
, ponieważ używają proxy lub opakowania.yarn add manual-promise
npn install manual-promise
https://github.com/zpxp/manual-promise#readme
źródło
A może stworzysz funkcję przechwytywania odrzucenia i zwrotu?
źródło
Złożyłem listę, która spełnia tę funkcję: https://gist.github.com/thiagoh/c24310b562d50a14f3e7602a82b4ef13
oto jak powinieneś go użyć:
źródło
najpierw włącz --allow-natives-syntax w przeglądarce lub węźle
źródło
To kolejne rozwiązanie, które rozwiązuje obietnicę z zewnątrz
Stosowanie
źródło