Niezależnie od tego, czy jest to obietnica ES6, czy obietnica bluebird, obietnica Q itp.
Jak sprawdzić, czy dany obiekt jest obietnicą?
javascript
promise
q
bluebird
es6-promise
theram
źródło
źródło
.then
metodę, ale to nie powiedziałoby ci, że to, co masz, jest zdecydowanie obietnicą. W tym momencie wiedziałbyś tylko, że masz coś, co obnaża.then
metodę, na przykład obietnicę..then
metodę, która nie jest Obietnicą, nie zachowuje się jak Obietnica i nie miał zamiaru być używany jak Obietnica. Sprawdzanie.then
metody informuje tylko, że jeśli obiekt nie ma.then
metody, to nie masz obietnicy. Odwrotna - że istnienie.then
metody oznacza, że zrobić mają obietnicę - niekoniecznie jest prawdą..then
metodę. Tak, ma to potencjał fałszywych trafień, ale jest to założenie, na którym polegają wszystkie biblioteki obiecujące (ponieważ tylko na tym mogą polegać). Jedyną alternatywą, jaką widzę, jest skorzystanie z sugestii Benjamina Gruenbauma i przejrzenie jej przez pakiet testów obietnic. Ale to nie jest praktyczne w przypadku rzeczywistego kodu produkcyjnego.Odpowiedzi:
Jak decyduje biblioteka obietnic
Jeśli ma jakąś
.then
funkcję - jest to jedyna standardowa używana biblioteka bibliotek obietnic.Specyfikacja Promises / A + ma pojęcie „
then
zdolny”, które jest w zasadzie „przedmiotem zthen
metodą”. Obietnice będą i powinny przyswoić sobie wszystko za pomocą ówczesnej metody. Wszystkie wspomniane obietnice wykonania to robią.Jeśli spojrzymy na specyfikację :
Wyjaśnia również uzasadnienie tej decyzji projektowej:
Jak powinieneś zdecydować
Nie powinieneś - zamiast tego zadzwoń
Promise.resolve(x)
(Q(x)
w Q), który zawsze przekształci dowolną wartość lub zewnętrznąthen
zdolność w zaufaną obietnicę. Jest to bezpieczniejsze i łatwiejsze niż samodzielne przeprowadzanie tych kontroli.naprawdę musisz być pewien?
Zawsze możesz uruchomić go za pomocą zestawu testów : D
źródło
Sprawdzanie, czy coś jest obiecane, niepotrzebnie komplikuje kod, wystarczy użyć
Promise.resolve
źródło
Oto moja pierwotna odpowiedź, która została ratyfikowana w specyfikacji jako sposób na sprawdzenie obietnicy:
Działa to, ponieważ algorytm wyraźnie wymaga,
Promise.resolve
aby zwracał dokładnie przekazany obiekt wtedy i tylko wtedy, gdy jest to obietnica z definicji specyfikacji.Mam tutaj inną odpowiedź, która kiedyś to mówiła, ale zmieniłem ją na coś innego, gdy w tym czasie nie działała z Safari. To było rok temu, a teraz działa niezawodnie nawet w Safari.
Zredagowałbym moją pierwotną odpowiedź, z wyjątkiem tego, że czułem się źle, biorąc pod uwagę, że więcej osób głosowało teraz na zmienione rozwiązanie w tej odpowiedzi niż w oryginale. Wierzę, że to lepsza odpowiedź i mam nadzieję, że się zgadzasz.
źródło
===
zamiast==
?Aktualizacja: To nie jest już najlepsza odpowiedź. Zamiast tego proszę głosować na moją drugą odpowiedź .
powinien to zrobić. Pamiętaj, że może to działać niezawodnie tylko z natywnymi obietnicami es6.
Jeśli używasz podkładki dystansowej, biblioteki obietnic lub czegokolwiek innego, co udaje, że jest podobna do obietnicy, bardziej odpowiednie może być przetestowanie „niemożliwego” (cokolwiek za pomocą
.then
metody), jak pokazano w innych odpowiedziach tutaj.źródło
Promise.resolve(obj) == obj
nie będzie działać w Safari. Użyjinstanceof Promise
zamiast tego.obj && typeof obj.then == 'function'
, ponieważ będzie działał ze wszystkimi typami obietnic i jest w rzeczywistości sposobem zalecanym przez specyfikację i używanym przez implementacje / polifill. NatywnyPromise.all
na przykład działa na wszystkichthen
umiejętnościach, nie tylko na innych rodzimych obietnicach. Twój kod też powinien. Toinstanceof Promise
nie jest dobre rozwiązanie.console.log(typeof p, p, p instanceof Promise);
produkuje ten wyjściowe:object Promise { <pending> } false
. Jak widać, jest to obietnica w porządku - a jednakinstanceof Promise
test powracafalse
?źródło
Aby sprawdzić, czy dany obiekt jest obietnicą ES6 , możemy skorzystać z tego predykatu:
Call
ingtoString
bezpośrednio zObject.prototype
zwraca natywną reprezentację ciągu danego typu obiektu, co"[object Promise]"
w naszym przypadku. Zapewnia to, że dany obiekttoString
metodą danego obiektu.instanceof
lubisPrototypeOf
.Jednak każdy konkretny obiekt hosta , który ma zmodyfikowany znacznik
Symbol.toStringTag
, może zwrócić"[object Promise]"
. Może to być zamierzony wynik lub nie, zależnie od projektu (np. Jeśli istnieje niestandardowa implementacja Promise).Aby sprawdzić, czy obiekt pochodzi z natywnej obietnicy ES6 , możemy użyć:
Zgodnie z tą i niniejszą sekcją specyfikacji ciąg reprezentujący funkcję powinien być:
co jest odpowiednio obsługiwane powyżej. FunctionBody jest
[native code]
we wszystkich głównych przeglądarkach.MDN:
Function.prototype.toString
Działa to również w wielu kontekstach środowiska.
źródło
Nie jest to odpowiedź na pełne pytanie, ale myślę, że warto wspomnieć, że w Node.js 10
isPromise
została dodana nowa funkcja wywołana, która sprawdza, czy obiekt jest rodzimą obietnicą, czy nie:źródło
Oto jak pakiet graphql-js wykrywa obietnice:
value
jest zwróconą wartością twojej funkcji. Używam tego kodu w moim projekcie i jak dotąd nie mam z tym problemu.źródło
Oto formularz kodu https://github.com/ssnau/xkit/blob/master/util/is-promise.js
jeśli obiekt z
then
metodą, powinien być traktowany jakoPromise
.źródło
Jeśli używasz Typescript , chciałbym dodać, że możesz użyć funkcji „predykat typu”. Powinien po prostu zawrzeć logiczną weryfikację w funkcji, która powraca,
x is Promise<any>
i nie trzeba wykonywać typecastów. Poniżej na moim przykładziec
znajduje się albo obietnica, albo jeden z moich typów, który chcę przekształcić w obietnicę, wywołującc.fetch()
metodę.Więcej informacji: https://www.typescriptlang.org/docs/handbook/advanced-types.html
źródło
Jeśli używasz metody asynchronicznej, możesz to zrobić i uniknąć niejasności.
Jeśli funkcja zwróci obietnicę, będzie oczekiwać i powróci z rozstrzygniętą wartością. Jeśli funkcja zwróci wartość, zostanie potraktowana jako rozwiązana.
Jeśli funkcja nie zwróci dziś obietnicy, ale jutro zwróci obietnicę lub zostanie uznana za asynchroniczną, będziesz zabezpieczony na przyszłość.
źródło
Promise.resolve()
źródło
Używam tej funkcji jako uniwersalnego rozwiązania:
źródło
po znalezieniu niezawodnego sposobu na wykrycie funkcji asynchronicznych, a nawet obietnic , zakończyłem testem:
źródło
Promise
i tworzysz tego wystąpienia, ten test może się nie powieść. powinno to jednak działać w przypadku większości tego, co próbujesz przetestować.fn.constructor.name === 'AsyncFunction'
jest źle - oznacza to, że coś jest funkcją asynchroniczną, a nie obietnicą - nie gwarantuje się też, że zadziała, ponieważ ludzie mogą podklasować obietniceES6:
źródło
toString
metodę, może po prostu zwrócić ciąg zawierający"Promise"
.'NotAPromise'.toString().includes('Promise') === true