मेरा अतुल्यकालिक फ़ंक्शन मान के बजाय वादा {<लंबित>} वापस क्यों कर रहा है?


129

मेरा कोड:

let AuthUser = data => {
  return google.login(data.username, data.password).then(token => { return token } )
}

और जब मैं कुछ इस तरह से चलाने की कोशिश करता हूं:

let userToken = AuthUser(data)
console.log(userToken)

मैं ला रहा हूँ:

Promise { <pending> }

पर क्यों?

मेरा मुख्य लक्ष्य टोकन प्राप्त करना है google.login(data.username, data.password)जिससे एक वादा, एक चर में वापस आ जाता है। और उसके बाद ही कुछ क्रियाओं को करना चाहिए।


1
@ Lo @cFaure-Lacroix, इस लेख को देखें: medium.com/@bluepnume/…
Src

@ Lo @cFaure-Lacroix getFirstUserफ़ंक्शन पर देखो
Src

तो इसका क्या? यह एक वादा वापस करने वाला एक समारोह है।
Lo16c Faure-Lacroix

1
@ Lo @cFaure-Lacroix तो आपका मतलब है कि उस उदाहरण में भी हमें getFirstUser फ़ंक्शन में लौटने वाले डेटा वादा का उपयोग करने की आवश्यकता है?
श्रीमती

उस उदाहरण के लिए हां, ES7 सिंटैक्स "वेट" का उपयोग करने का एकमात्र तरीका है जो वादे के परिणाम की प्रतीक्षा करने के लिए वर्तमान संदर्भ के निष्पादन को रोकने के लिए लगता है। यदि आप लेख पढ़ते हैं तो आप इसे देखेंगे। लेकिन चूंकि ES7 शायद अभी तक लगभग समर्थित नहीं है, हां। "तब" यह बहुत सुंदर है।
Lo16c Faure-Lacroix

जवाबों:


176

वादा हमेशा लंबित रहेगा, जब तक कि उसके परिणाम अभी तक हल नहीं हुए हैं। आपको .thenवादे की स्थिति की परवाह किए बिना परिणामों को पकड़ने के वादे पर कॉल करना चाहिए (हल या अभी भी लंबित):

let AuthUser = function(data) {
  return google.login(data.username, data.password).then(token => { return token } )
}

let userToken = AuthUser(data)
console.log(userToken) // Promise { <pending> }

userToken.then(function(result) {
   console.log(result) // "Some User token"
})

ऐसा क्यों है?

वादे ही आगे की दिशा होते हैं; आप केवल एक बार उन्हें हल कर सकते हैं। किसी का हल किया गया मान Promiseउसके .thenया .catchविधियों के लिए दिया गया है ।

विवरण

वादे के अनुसार / A + युक्ति:

वादा समाधान प्रक्रिया एक अमूर्त ऑपरेशन है जो एक वादा और एक मूल्य के रूप में लिया जाता है, जिसे हम [[संकल्प]] (वादा, x) के रूप में दर्शाते हैं। यदि x एक ज्वलनशील है, तो यह वादा करता है कि x की अवस्था को अपनाने का वादा किया गया है, इस धारणा के तहत कि x कम से कम कुछ वादे की तरह व्यवहार करता है। अन्यथा, यह मान x के साथ वादा पूरा करता है।

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

यह युक्ति पार्स करने के लिए थोड़ा कठिन है, तो चलो इसे तोड़ दें। नियम है:

यदि .thenहैंडलर में फ़ंक्शन एक मान लौटाता है, तो Promiseउस मान के साथ हल होता है। यदि हैंडलर दूसरा लौटाता है Promise, तो मूल Promiseजंजीर के हल मूल्य के साथ हल होता है Promise। अगले .thenहैंडलर में हमेशा पूर्ववर्ती में लौटाए गए जंजीर वाले वादे का सुलझा हुआ मूल्य होगा .then

जिस तरह से यह वास्तव में काम करता है वह नीचे और अधिक विवरण में वर्णित है:

1. .thenसमारोह की वापसी वादे का हल मूल्य होगा।

function initPromise() {
  return new Promise(function(res, rej) {
    res("initResolve");
  })
}

initPromise()
  .then(function(result) {
    console.log(result); // "initResolve"
    return "normalReturn";
  })
  .then(function(result) {
    console.log(result); // "normalReturn"
  });

2. यदि .thenफ़ंक्शन एक लौटता है Promise, तो उस जंजीर वादे का हल किया गया मूल्य निम्नलिखित को पारित किया जाता है .then

function initPromise() {
  return new Promise(function(res, rej) {
    res("initResolve");
  })
}

initPromise()
  .then(function(result) {
    console.log(result); // "initResolve"
    return new Promise(function(resolve, reject) {
       setTimeout(function() {
          resolve("secondPromise");
       }, 1000)
    })
  })
  .then(function(result) {
    console.log(result); // "secondPromise"
  });

आपका पहला काम नहीं कर रहा है। Uncaught SyntaxError: Unexpected token .। दूसरे के लिए वापसी की जरूरत हैPromise
zamil

@zamil को आपको दूसरे उदाहरण में फ़ंक्शन को लागू करना होगा। आप .thenएक बिन बुलाए फ़ंक्शन पर नहीं कर सकते । उत्तर को अद्यतन किया
बामिह

1
मैं इसे बुकमार्क कर रहा हूं ताकि मैं इसे हमेशा के लिए रख सकूं। मैं वास्तव में वादों का निर्माण करने के लिए वास्तव में स्पष्ट और पठनीय नियमों को खोजने के लिए एक बहुत लंबे समय से काम कर रहा हूं। वादे / A + युक्ति का आपका ब्लॉककाउंट एक आदर्श उदाहरण है कि यह स्व-शिक्षा वादों के लिए PITA क्यों रहा है। यह भी केवल समय है जब मैंने सेटटाइमआउट का उपयोग किया है, जहां यह पाठ को स्वयं भ्रमित नहीं करता था। और उत्कृष्ट संदर्भ, धन्यवाद।
मोनस्टो

21

मुझे पता है कि यह प्रश्न 2 साल पहले पूछा गया था, लेकिन मैं एक ही मुद्दे में भाग लेता हूं और समस्या का उत्तर ईएस 6 के बाद से है, कि आप केवल awaitफ़ंक्शन मान वापस कर सकते हैं, जैसे:

let AuthUser = function(data) {
  return google.login(data.username, data.password).then(token => { return token } )
}

let userToken = await AuthUser(data)
console.log(userToken) // your data

3
आप की जरूरत नहीं है .then(token => return token), यह सिर्फ एक अनावश्यक passthrough है। बस Google लॉगिन कॉल लौटाएं।
सोवियुत 21:19

यह उत्तर प्रश्न से असंबंधित है। मूल पोस्टर की समस्या का ES6 'async / प्रतीक्षा से कोई लेना-देना नहीं है। ECMAScript 2017 में इस नई सिंथैटिक शुगर को पेश करने से पहले वादे मौजूद थे और उन्होंने "हुड के तहत" वादे का इस्तेमाल किया। एमडीएन को async / प्रतीक्षा पर देखें ।
try-

ES8 / Nodejs के लिए, यदि आप awaitकिसी async फ़ंक्शन के बाहर का उपयोग करते हैं, तो त्रुटियों को फेंक दिया जाता है। शायद इसका बेहतर उदाहरण यह है कि यह AuthUserसमारोह होगा async, जो तब समाप्त होता हैreturn await google.login(...);
जॉन एल।

4

thenविधि एक लंबित वादा जो करने के लिए कॉल में पंजीकृत एक परिणाम हैंडलर की वापसी मान द्वारा अतुल्यकालिक रूप से हल किया जा सकता देता है then, या हैंडलर कहा जाता है के अंदर एक त्रुटि फेंक द्वारा अस्वीकार कर दिया।

इसलिए कॉलिंग AuthUserअचानक उपयोगकर्ता को समकालिक रूप से लॉग इन नहीं करेगा, लेकिन एक वादा लौटाता है जिसके लॉगिन सफल होने (या विफल होने) के बाद पंजीकृत हैंडलर को बुलाया जाएगा। मेरा सुझाव thenहै कि लॉगिन वादा के एक खंड द्वारा सभी लॉगिन प्रोसेसिंग को ट्रिगर किया जाए । प्रवाह के अनुक्रम को उजागर करने के लिए नामित कार्यों का उपयोग करते हुए ईजी:

let AuthUser = data => {   // just the login promise
  return google.login(data.username, data.password);
};

AuthUser(data).then( processLogin).catch(loginFail);

function processLogin( token) {
      // do logged in stuff:
      // enable, initiate, or do things after login
}
function loginFail( err) {
      console.log("login failed: " + err);
}

1

वादों पर एमडीएन अनुभाग देखें विशेष रूप से, तब के रिटर्न प्रकार को देखें ()।

लॉग-इन करने के लिए, उपयोगकर्ता-एजेंट को सर्वर को एक अनुरोध सबमिट करना होगा और प्रतिक्रिया प्राप्त करने की प्रतीक्षा करनी होगी। चूंकि आपके आवेदन को पूरी तरह से रोकना एक अनुरोध के दौरान राउंड-ट्रिप आम तौर पर एक बुरे उपयोगकर्ता अनुभव के लिए बनाता है, व्यावहारिक रूप से हर जेएस फ़ंक्शन जो आपको लॉग इन करता है (या किसी अन्य रूप में सर्वर इंटरैक्शन करता है) एक प्रॉमिस का उपयोग करेगा, या इसे बहुत पसंद करेगा , अतुल्यकालिक परिणाम देने के लिए।

अब, यह भी ध्यान दें कि returnकथन का मूल्यांकन हमेशा उस फ़ंक्शन के संदर्भ में किया जाता है जिसमें वे दिखाई देते हैं। इसलिए जब आपने लिखा हो:

let AuthUser = data => {
  return google
    .login(data.username, data.password)
    .then( token => {
      return token;
    });
};

बयान का return token;मतलब यह था कि अनाम फ़ंक्शन को पारित किया then()जाना चाहिए, टोकन लौटना चाहिए, न कि AuthUserफ़ंक्शन को। AuthUserकॉलिंग का परिणाम क्या है google.login(username, password).then(callback);, जो एक वादा होता है।

अंततः आपका कॉलबैक token => { return token; }कुछ नहीं करता है; इसके बजाय, आपके इनपुट को then()एक फ़ंक्शन होना चाहिए जो वास्तव में टोकन को किसी तरह से संभालता है।


@Src मैंने अपना उत्तर लिखने से पहले पूछने वाले को स्पष्ट किया कि वे एक मूल्य को समकालिक रूप से वापस करने के लिए रास्ता ढूंढ रहे हैं , और कोड स्निपेट द्वारा अनुमान लगाया जा सकता है कि परे उनके देव वातावरण या भाषा संस्करण के बारे में धारणा बनाए बिना - अर्थात, यह सुरक्षित है ईएस 6 मानने के लिए, लेकिन जरूरी नहीं कि ईएस 7।
जेसी अमानो

@ अहदामबीह ठीक है, करेंगे। मुझे लगता है कि समस्या यह है कि मैं गलत समझा है कि returnनए (ish) क्लोजर सिंटैक्स के साथ कैसे व्यवहार किया जाता है, इस मामले में - ठीक है, मैं दृढ़ता से उस से दूर हो जाता हूं, लेकिन त्रुटि अभी भी मेरी है और मैं इसके लिए माफी चाहता हूं।
जेसी अमानो

2
@ अहमदमीह एर, मैं वास्तव में उस हिस्से को जानता था, यही कारण है कि मैंने दावा किया कि यह दावा करने के विपरीत token => { return token; } कुछ भी नहीं है यह उल्टा था। आप कह सकते हैं google.login(username, password).then(token=>{return token;}).then(token=>{return token;})और आगे हमेशा के लिए, लेकिन आप केवल एक वापसी को प्राप्त करेंगे Promiseजो एक टोकन के साथ हल होती है - जैसे कि आपने अभी इसे छोड़ दिया है google.login(username, password);। मुझे यकीन नहीं है कि आपको क्यों लगता है कि यह "बहुत गलत" है।
जेसी अमानो

1
@ अहमदमीह: क्या आप इस बारे में अधिक विशिष्ट हो सकते हैं कि पाठ के इस टुकड़े में क्या गलत है? मुझे कुछ भी दिखाई नहीं दे रहा है, वह सिर्फ यही बताता है कि return tokenओपी शायद उम्मीद के मुताबिक काम क्यों नहीं करता।
बरगी

3
@ अहमदमीह: वास्तव में गलतफहमी है। हम तीनों अच्छी तरह से जानते हैं कि वादे कैसे काम करते हैं, कथन यह है कि promise.then(result => { return result; })बिल्कुल बराबर है promise, इसलिए विधि कॉल कुछ भी नहीं करता है और कोड को सरल बनाने और पठनीयता बढ़ाने के लिए गिरा दिया जाना चाहिए - एक बयान जो पूरी तरह से सच है।
बरगी

1

आपका वादा लंबित है, इसे पूरा करें

userToken.then(function(result){
console.log(result)
})

आपके शेष कोड के बाद। यह सब कोड है जो .then()आपके वादे को पूरा करता है और अंतिम परिणाम को परिणाम चर और कंसोल में परिणाम प्रिंट करता है। ध्यान रखें, आप परिणाम को वैश्विक चर में संग्रहीत नहीं कर सकते। आशा है कि स्पष्टीकरण आपकी मदद कर सकता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.