मैं कैसे बताऊं कि कोई वस्तु एक वादा है?


336

चाहे वह ईएस 6 प्रॉमिस हो या ब्लूबर्ड प्रॉमिस, क्यू प्रॉमिस आदि।

मैं यह देखने के लिए परीक्षण कैसे करूं कि कोई दी गई वस्तु एक वादा है?


3
सबसे अच्छी तरह से आप एक .thenविधि की जाँच कर सकते हैं , लेकिन यह आपको यह नहीं बताएगा कि आपके पास क्या है एक वादा निश्चित रूप से। उस बिंदु पर आप सभी को पता होगा कि आपके पास कुछ ऐसा है जो एक .thenविधि को उजागर करता है , जैसे एक वादा।
स्कॉट ऑफेन

@ScottOffen वादा विनिर्देश स्पष्ट रूप से एक भेद नहीं करता है।
बेंजामिन ग्रुएनबाम

6
मेरा कहना यह है कि कोई भी एक ऐसी वस्तु बना सकता है जो एक ऐसी .thenविधि को उजागर करती है जो एक वादा नहीं है, वह एक वादे की तरह व्यवहार नहीं करता है और एक वादा की तरह इस्तेमाल किए जाने का कोई इरादा नहीं था। एक .thenविधि के लिए जाँच करना आपको बताता है कि यदि वस्तु में विधि नहीं है .then, तो आपके पास एक वादा नहीं है। उलटा - कि एक के अस्तित्व .thenविधि का मतलब है कि आप कर एक वादा है - जरूरी सच नहीं है।
स्कॉट ऑफेन

3
@ScottOffen परिभाषा के अनुसार, एक वादे की पहचान करने का एकमात्र स्थापित तरीका यह जांचना है कि क्या यह एक .thenविधि है। हां, यह झूठी सकारात्मकता की क्षमता है, लेकिन यह धारणा है कि सभी वादा पुस्तकालयों पर भरोसा करते हैं (क्योंकि यह सब उन पर भरोसा कर सकता है)। जहाँ तक मैं देख सकता हूँ एकमात्र विकल्प बेंजामिन ग्रुएनबाम का सुझाव है और इसे वादे परीक्षण सूट के माध्यम से चलाना है। लेकिन यह वास्तविक उत्पादन कोड के लिए व्यावहारिक नहीं है।
JLRishe

जवाबों:


342

एक वादा पुस्तकालय कैसे तय करता है

यदि यह एक .thenफ़ंक्शन है - यह केवल मानक वादा पुस्तकालयों का उपयोग है।

वादे / ए + विनिर्देश में एक धारणा है thenजो सक्षम है, जो मूल रूप से "एक thenविधि के साथ एक वस्तु " है। वादा करता है और फिर एक विधि के साथ कुछ भी आत्मसात करना चाहिए । आपके द्वारा किए गए वादे के क्रियान्वयन के सभी लोग ऐसा करते हैं।

यदि हम विनिर्देश देखें :

2.3.3.3 यदि thenकोई फ़ंक्शन है, तो इसे x के साथ कॉल करें, पहला तर्क हल करें, और दूसरा तर्क अस्वीकार करें

यह इस डिजाइन निर्णय के औचित्य की भी व्याख्या करता है:

thenएबल्स का यह उपचार तब तक वादे के क्रियान्वयन की अनुमति देता है, जब तक वे एक वादा / ए + पूर्ण thenविधि का खुलासा नहीं करते । यह वादा करता है / ए + कार्यान्वयन के लिए उचित तो तरीकों के साथ गैर-अनुरूप कार्यान्वयन को "आत्मसात" करने की अनुमति देता है।

आपको कैसे तय करना चाहिए

आपको ऐसा नहीं करना चाहिए - इसके बजाय Promise.resolve(x)( Q(x)क्यू में) कॉल करें जो हमेशा किसी भी मूल्य या बाहरी thenसक्षम को एक विश्वसनीय वादा में बदल देगा। इन जाँचों को स्वयं करना अधिक सुरक्षित और आसान है।

वास्तव में सुनिश्चित करने की आवश्यकता है?

आप इसे हमेशा टेस्ट सूट के माध्यम से चला सकते हैं : डी


168

अगर कुछ वादा किया गया है तो यह जाँचना अनावश्यक रूप से कोड को जटिल करता है, बस उपयोग करें Promise.resolve

Promise.resolve(valueOrPromiseItDoesntMatter).then(function(value) {

})

1
तो Promise.resolve अपने रास्ते में आने वाली किसी भी चीज़ को संभाल सकता है ? निश्चित रूप से कुछ भी नहीं, लेकिन मुझे लगता है कि कुछ भी उचित है?
अलेक्जेंडर मिल्स

3
@AlexMills हाँ, यह jQuery के वादे जैसे गैर मानक वादों के लिए भी काम करता है। यह विफल हो सकता है यदि ऑब्जेक्ट में एक तत्कालीन विधि है जिसमें वादे से पूरी तरह से अलग इंटरफ़ेस है।
एस्लेइजा

19
यह जवाब, हालांकि शायद अच्छी सलाह है, वास्तव में सवाल का जवाब नहीं देता है।
स्टिजन डे विट

4
जब तक प्रश्न वास्तव में किसी को वास्तव में एक वादा पुस्तकालय को लागू करने के बारे में है, सवाल अमान्य है। केवल एक वादा पुस्तकालय को चेक करने की आवश्यकता होगी, उसके बाद आप हमेशा इसकी .resolve पद्धति का उपयोग कर सकते हैं जैसे मैंने दिखाया।
एस्लेइजा

4
@Esalija प्रश्न मुझे प्रासंगिक और महत्वपूर्ण प्रतीत होता है, न कि केवल एक वादे के कार्यान्वयन के लिए। यह एक वादा पुस्तकालय के एक उपयोगकर्ता के लिए भी प्रासंगिक है जो जानना चाहता है कि कार्यान्वयन कैसे होगा / व्यवहार करना चाहिए और कैसे अलग-अलग वादा पुस्तकालय एक-दूसरे के साथ बातचीत करेंगे। विशेष रूप से, यह उपयोगकर्ता इस तथ्य से बहुत निराश है कि मैं किसी भी एक्स के लिए एक्स का वादा कर सकता हूं सिवाय इसके कि जब एक्स "वादा" (जो भी "वादा" का अर्थ यहां है - यही सवाल है), और मुझे निश्चित रूप से दिलचस्पी है यह जानना कि वास्तव में उस अपवाद की सीमा कहाँ है।
डॉन हैच

103

यहाँ मेरा मूल उत्तर है, जो बाद में कल्पना में प्रमाणित किया गया है कि वादे के लिए परीक्षण करने का तरीका:

Promise.resolve(obj) == obj

यह काम करता है क्योंकि एल्गोरिथ्म स्पष्ट रूप से मांग करता है कि इसमें Promise.resolveपारित की गई सटीक वस्तु वापस आनी चाहिए और केवल अगर यह कल्पना की परिभाषा के अनुसार एक वादा है।

मेरे पास यहाँ एक और उत्तर है, जो यह कहता था, लेकिन मैंने इसे उस समय कुछ और के लिए बदल दिया जब यह सफारी के साथ काम नहीं करता था। यह एक साल पहले था, और यह अब सफारी में भी मज़बूती से काम करता है।

मैंने अपना मूल उत्तर संपादित कर दिया होगा, सिवाय इसके कि गलत लगा, यह देखते हुए कि अब तक मूल से अधिक लोगों ने उस उत्तर में परिवर्तित समाधान के लिए मतदान किया है। मेरा मानना ​​है कि यह बेहतर उत्तर है, और मुझे आशा है कि आप सहमत होंगे।


10
के ===बजाय आप का उपयोग करना चाहिए ==?
नील एस।

12
यह उन वादों के लिए भी विफल होगा जो समान दायरे के नहीं हैं।
बेंजामिन ग्रुएनबाम

4
"वादे की परिभाषा के द्वारा एक वादा" का अर्थ लगता है "एक ही निर्माता द्वारा वादा किए गए वादे के रूप में वादा किया गया वादा के रूप में बनाया गया था। समाधान () होगा" - इसलिए यह पता लगाने में विफल रहेगा यदि उदा।
पॉलीफ़िल्ड

3
इस उत्तर को बेहतर बनाया जा सकता है यदि यह बताते हुए शुरू होता है कि आप इस सवाल की व्याख्या कैसे कर रहे हैं बजाय एक उत्तर के साथ शुरू करने के बजाय - ओपी ने दुर्भाग्य से इसे बिल्कुल स्पष्ट नहीं किया है, और आप या तो इस बिंदु पर नहीं हैं, इसलिए ओपी, लेखक और पाठक 3 अलग-अलग पृष्ठों पर होने की संभावना है। डॉक्टर आपको "यदि तर्क इस निर्माता द्वारा उत्पादित एक वादा है" कहते हैं , तो इटैलिकाइज्ड हिस्सा महत्वपूर्ण है। यह बताना अच्छा होगा कि आप जिस प्रश्न का उत्तर दे रहे हैं। यह भी कि आपका उत्तर इस लाइब्रेरी के उपयोगकर्ता के लिए उपयोगी है, लेकिन कार्यान्वयनकर्ता के लिए नहीं।
डॉन हैच

1
इस विधि का उपयोग न करें, यहाँ क्यों, @ बेंजामिन ग्रुएनबाम के बिंदु से अधिक है। gist.github.com/reggi/a1da4d0ea4f1320fa15405fb86358cff
ThomasReggi

61

अद्यतन: यह अब सबसे अच्छा जवाब नहीं है। कृपया इसके बजाय मेरे दूसरे जवाब को वोट दें ।

obj instanceof Promise

करना चाहिए। ध्यान दें कि यह केवल देशी es6 वादों के साथ मज़बूती से काम कर सकता है।

यदि आप एक शिम का उपयोग कर रहे हैं, एक वादा पुस्तकालय या कुछ और जैसा कि वादा करने का ढोंग कर रहे हैं, तो यह "जवाबदेह" (एक .thenविधि के साथ कुछ भी ) के लिए परीक्षण करने के लिए अधिक उपयुक्त हो सकता है , जैसा कि यहां अन्य उत्तरों में दिखाया गया है।


इसके बाद से मुझे बताया गया है कि Promise.resolve(obj) == objसफारी में काम नहीं किया जाएगा। instanceof Promiseइसके बजाय उपयोग करें ।
जिब

2
यह मज़बूती से काम नहीं करता है और मुझे समस्या को ट्रैक करने के लिए एक पागलपनपूर्ण कारण है। मान लें कि आपके पास एक पुस्तकालय है जो es6.promise शिम का उपयोग करता है, और आप कहीं कहीं ब्लूबर्ड का उपयोग करते हैं, तो आपको समस्याएं होंगी। यह मुद्दा मेरे लिए क्रोम कैनरी में आया।
विघ्न

1
हां, यह जवाब वास्तव में गलत है। मैं समस्या को ट्रैक करने के लिए इतनी कड़ी मेहनत के लिए यहाँ समाप्त हुआ। आपको वास्तव में obj && typeof obj.then == 'function'इसके बजाय जांच करनी चाहिए , क्योंकि यह सभी प्रकार के वादों के साथ काम करेगा और वास्तव में युक्ति द्वारा अनुशंसित तरीका है और कार्यान्वयन / पॉलीफिल द्वारा उपयोग किया जाता है। Promise.allउदाहरण के लिए मूलनिवासी thenअन्य सभी मूल वादों पर ही नहीं, सभी क्षेत्रों पर काम करेगा । तो आपका कोड चाहिए। तो instanceof Promiseएक अच्छा समाधान नहीं है।
स्टिजन डे विट

2
फॉलोअप - यह बदतर है: केवल मूल वादों का उपयोग करके नोड.जेएस 6.2.2 पर मैं अभी एक समस्या को डिबग करने की कोशिश कर रहा हूं जहां console.log(typeof p, p, p instanceof Promise);यह आउटपुट उत्पन्न करता है object Promise { <pending> } false:। जैसा कि आप देख सकते हैं यह एक वादा ठीक है - और अभी तक instanceof Promiseपरीक्षण रिटर्न false?
मोर

2
यह उन वादों के लिए विफल होगा जो समान दायरे के नहीं हैं।
बेंजामिन ग्रुएनबाम

46
if (typeof thing.then === 'function') {
    // probably a promise
} else {
    // definitely not a promise
}

6
क्या होगा अगर बात अपरिभाषित है? आपको उस चीज़ के खिलाफ पहरा देने की आवश्यकता है && ...
mrBorna

सबसे अच्छा नहीं है, लेकिन निश्चित रूप से बहुत संभावना है; समस्या के दायरे पर भी निर्भर करता है। 100% रक्षात्मक रूप से लिखना आमतौर पर खुले अंत वाले सार्वजनिक एपीआई में लागू होता है या जहां आप जानते हैं कि डेटा का आकार / हस्ताक्षर पूरी तरह से खुले-समाप्त हैं।
रोब

17

यह देखने के लिए कि क्या दी गई वस्तु ES6 वादा है , हम इस विधेय का उपयोग कर सकते हैं:

function isPromise(p) {
  return p && Object.prototype.toString.call(p) === "[object Promise]";
}

Calling toStringसे सीधे Object.prototypeएक रिटर्न देशी स्ट्रिंग प्रतिनिधित्व दिया ऑब्जेक्ट प्रकार जो है की "[object Promise]"हमारे मामले में। यह सुनिश्चित करता है कि दी गई वस्तु

  • इस तरह के रूप में झूठी सकारात्मक बाईपास:
    • एक ही निर्माता के नाम ("वादा") के साथ स्व-परिभाषित ऑब्जेक्ट प्रकार।
    • toStringदी गई वस्तु की स्व-लिखित विधि।
  • या इसके विपरीतinstanceof कई पर्यावरण संदर्भों (जैसे iframes) पर काम करता है isPrototypeOf

हालाँकि, कोई विशेष होस्ट ऑब्जेक्ट , जिसके टैगSymbol.toStringTag को इसके माध्यम से संशोधित किया गया है , वापस आ सकता है "[object Promise]"। यह अपेक्षित परिणाम हो सकता है या परियोजना के आधार पर नहीं हो सकता है (जैसे कि कोई कस्टम वादा लागू हो)।


यह देखने के लिए कि ऑब्जेक्ट देशी ES6 प्रॉमिस से है , हम उपयोग कर सकते हैं:

function isNativePromise(p) {
  return p && typeof p.constructor === "function"
    && Function.prototype.toString.call(p.constructor).replace(/\(.*\)/, "()")
    === Function.prototype.toString.call(/*native object*/Function)
      .replace("Function", "Promise") // replacing Identifier
      .replace(/\(.*\)/, "()"); // removing possible FormalParameterList 
}

इस और इस खंड के अनुसार , फ़ंक्शन का स्ट्रिंग प्रतिनिधित्व होना चाहिए:

"समारोह पहचानकर्ता ( FormalParameterList ऑप्ट ) { FunctionBody }"

जो ऊपर के अनुसार संभाला जाता है। FunctionBody है [native code]सभी प्रमुख ब्राउज़रों में।

MDN: Function.prototype.toString

यह कई पर्यावरण संदर्भों के साथ-साथ काम करता है।


12

पूर्ण प्रश्न का उत्तर नहीं है, लेकिन मुझे लगता है कि यह उल्लेख के लायक है कि Node.js 10 में एक नए उपयोग फ़ंक्शन isPromiseको जोड़ा गया था जो यह जांचता है कि कोई वस्तु एक देशी वादा है या नहीं:

const utilTypes = require('util').types
const b_Promise = require('bluebird')

utilTypes.isPromise(Promise.resolve(5)) // true
utilTypes.isPromise(b_Promise.resolve(5)) // false

11

इस तरह से रेखांकन-जेएस पैकेज वादों का पता लगाता है:

function isPromise(value) {
  return Boolean(value && typeof value.then === 'function');
}

valueआपके फ़ंक्शन का दिया गया मान है। मैं अपने प्रोजेक्ट में इस कोड का उपयोग कर रहा हूं और मुझे अब तक कोई समस्या नहीं है।


6

यहाँ कोड फॉर्म https://github.com/ssnau/xkit/blob/master/util/is-promise.js है

!!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function';

यदि एक thenविधि के साथ एक वस्तु , यह एक के रूप में व्यवहार किया जाना चाहिए Promise


3
हमें obj === 'फ़ंक्शन' स्थिति btw की आवश्यकता क्यों है?
Alendorff

इस उत्तर के रूप में भी, किसी भी वस्तु का एक तरीका "तब" हो सकता है और इस तरह हमेशा एक वादा के रूप में नहीं माना जा सकता है।
बोगायन हॉफमैन

6

यदि आप टाइपस्क्रिप्ट का उपयोग कर रहे हैं , तो मैं यह जोड़ना चाहूंगा कि आप "प्रकार विधेय" सुविधा का उपयोग कर सकते हैं। बस एक फ़ंक्शन में तार्किक सत्यापन को लपेटना चाहिए जो वापस आता है x is Promise<any>और आपको टाइपकास्ट करने की आवश्यकता नहीं होगी। मेरे उदाहरण के नीचे, cया तो एक वादा है या मेरा एक प्रकार है जिसे मैं c.fetch()विधि कहकर एक वादा में बदलना चाहता हूं ।

export function toPromise(c: Container<any> | Promise<any>): Promise<any> {
    if (c == null) return Promise.resolve();
    return isContainer(c) ? c.fetch() : c;
}

export function isContainer(val: Container<any> | Promise<any>): val is Container<any> {
    return val && (<Container<any>>val).fetch !== undefined;
}

export function isPromise(val: Container<any> | Promise<any>): val is Promise<any> {
    return val && (<Promise<any>>val).then !== undefined;
}

अधिक जानकारी: https://www.typescriptlang.org/docs/handbook/advanced-types.html


6

यदि आप एक async विधि में हैं तो आप ऐसा कर सकते हैं और किसी भी अस्पष्टता से बच सकते हैं।

async myMethod(promiseOrNot){
  const theValue = await promiseOrNot()
}

यदि फ़ंक्शन प्रतिज्ञा देता है, तो वह प्रतीक्षा करेगा और हल किए गए मान के साथ लौटेगा। यदि फ़ंक्शन मान लौटाता है, तो इसे हल किया जाएगा।

यदि फ़ंक्शन आज एक वादा वापस नहीं करता है, लेकिन कल एक रिटर्न देता है या उसे एसिंक्स्ट घोषित किया जाता है, तो आप भविष्य के प्रमाण होंगे।


यह यहाँ के अनुसार काम करता है : "अगर [प्रतीक्षित] मूल्य एक वादा नहीं है, [प्रतीक्षारत अभिव्यक्ति] मूल्य को एक हल किए गए वादे में परिवर्तित करता है, और इसके लिए इंतजार करता है"
pqnet

यह मूल रूप से स्वीकार किए गए उत्तर में क्या सुझाव दिया गया है, सिवाय इसके कि यहां async- Promise.resolve()
wait

3
it('should return a promise', function() {
    var result = testedFunctionThatReturnsPromise();
    expect(result).toBeDefined();
    // 3 slightly different ways of verifying a promise
    expect(typeof result.then).toBe('function');
    expect(result instanceof Promise).toBe(true);
    expect(result).toBe(Promise.resolve(result));
});

2

मैं इस फ़ंक्शन को एक सार्वभौमिक समाधान के रूप में उपयोग करता हूं:

function isPromise(value) {
  return value && value.then && typeof value.then === 'function';
}

-1

Async फ़ंक्शंस या यहां तक ​​कि वादों का पता लगाने के लिए एक विश्वसनीय तरीके की खोज करने के बाद , मैंने निम्नलिखित परीक्षण का उपयोग किया:

() => fn.constructor.name === 'Promise' || fn.constructor.name === 'AsyncFunction'

यदि आप उप- Promiseपरीक्षा करते हैं और उस के उदाहरण बनाते हैं, तो यह परीक्षण विफल हो सकता है। यद्यपि आप इसके लिए परीक्षण करने की कोशिश कर रहे हैं, उसके अधिकांश के लिए काम करना चाहिए।
theram

सहमत हैं, लेकिन मैं यह नहीं देखता कि कोई क्यों वादों के उपशीर्षकों का निर्माण करेगा
सेबस्टियन एच।

fn.constructor.name === 'AsyncFunction'गलत है - इसका मतलब है कि कुछ एक async फ़ंक्शन है और एक वादा नहीं है - यह भी काम करने की गारंटी नहीं है, क्योंकि लोग वादों को
तोड़

@BenjaminGruenbaum उपरोक्त उदाहरण ज्यादातर मामलों में काम करता है, यदि आप अपना उपवर्ग बनाते हैं तो आपको इसके नाम पर परीक्षणों को जोड़ना चाहिए
सेबस्टियन एच।

आप कर सकते हैं, लेकिन अगर आप पहले से ही जानते हैं कि क्या वस्तुएं हैं तो आप पहले से ही जानते हैं कि सामान वादे हैं या नहीं।
बेंजामिन ग्रुएनबाम

-3

ES6:

const promise = new Promise(resolve => resolve('olá'));

console.log(promise.toString().includes('Promise')); //true

2
कोई भी वस्तु जिसके पास (या अधिलेखित) toStringविधि है, उसमें केवल एक स्ट्रिंग शामिल हो सकती है "Promise"
बोगीयन हॉफमैन

4
यह उत्तर कई कारणों से बुरा है, सबसे स्पष्ट है'NotAPromise'.toString().includes('Promise') === true
डैमड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.