আমার অ্যাসিঙ্ক্রোনাস ফাংশন কেন মানটির পরিবর্তে প্রতিশ্রুতি {<pend>> returning ফিরিয়ে দিচ্ছে?


127

আমার কোড:

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

তাহলে এটা কি? এটি একটি প্রতিশ্রুতি ফিরিয়ে ফাংশন।
Loïc Faure-Lacroix

1
@ LoïcFaure-Lacroix তাই আপনি বোঝাতে চাইছেন যে উদাহরণটিতেও getFirstUser ফাংশনে ফিরে ডেটা প্রতিশ্রুতি অ্যাক্সেস করার জন্য আমাদের তখন ব্যবহার করা দরকার?
এসআরসি

এই উদাহরণটিতে হ্যাঁ, কেবলমাত্র অন্য উপায়টি ES7 সিনট্যাক্সটি "অপেক্ষা করুন" ব্যবহার করা উচিত যা প্রতিশ্রুতিটির ফলাফলের জন্য অপেক্ষা করার জন্য বর্তমান প্রেক্ষাপটের সম্পাদন বন্ধ করার সমাধান করার জন্য মনে হয়। আপনি যদি নিবন্ধটি পড়েন তবে আপনি এটি দেখতে পাবেন। তবে যেহেতু ইএস 7 সম্ভবত এখনও কোথাও সমর্থিত নয়, হ্যাঁ। "তারপর" এটি বেশ অনেক বেশি।
Loïc Faure-Lacroix

উত্তর:


175

প্রতিশ্রুতি সর্বদা মুলতুবি থাকা লগ হবে যতক্ষণ না এর ফলাফলগুলি এখনও সমাধান হয় না। .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 পদ্ধতিতে ।

বিস্তারিত

প্রতিশ্রুতি অনুযায়ী / এ + স্পেস:

প্রতিশ্রুতি সমাধানের পদ্ধতিটি একটি বিমূর্ত অপারেশন যা ইনপুট হিসাবে একটি প্রতিশ্রুতি এবং একটি মান হিসাবে গ্রহণ করা হয়, যা আমরা [[সমাধান করুন]] (প্রতিশ্রুতি, এক্স) হিসাবে চিহ্নিত করি। 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"
  });

২. .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
জুমিল

@ জামিল আপনাকে দ্বিতীয় উদাহরণের মতো ফাংশনটি চালাতে হবে। আপনি .thenএকটি নিমন্ত্রিত ফাংশন করতে পারবেন না । উত্তরটি আপডেট করেছে
বামিহ

1
আমি এটি বুকমার্ক করছি যাতে আমি এটি চিরকাল ধরে রাখতে পারি আসলে কীভাবে প্রতিশ্রুতি তৈরি করা যায় তার সত্যিকারের স্পষ্ট এবং পঠনীয় নিয়মগুলি খুঁজে পেতে আমি খুব দীর্ঘ সময় ধরে কাজ করে যাচ্ছি। প্রতিশ্রুতিগুলি / এ + স্পপের আপনার ব্লককোটটি স্ব-শিক্ষাদানের প্রতিশ্রুতি দেওয়ার জন্য পিআইটিএ কেন হয়েছে তার একটি নিখুঁত উদাহরণ। এটি কেবলমাত্র একবারই আমি সেটটাইমআউট ব্যবহার করতে দেখেছি যেখানে এটি পাঠকে নিজেই বিভ্রান্ত করে না। এবং চমৎকার রেফারেন্স, আপনাকে ধন্যবাদ।
মনস্টো

21

আমি জানি এই প্রশ্নটি 2 বছর আগে জিজ্ঞাসা করা হয়েছিল, তবে আমি একই ইস্যুতে চলেছি এবং সমস্যার উত্তরটি ES6 সাল থেকে, আপনি কেবল 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), এটি কেবল একটি অপ্রয়োজনীয় পাস্ত্রথ্রু। কেবল গুগল লগইন কলটি ফিরিয়ে দিন।
সোভিয়েট

এই উত্তরটি প্রশ্নের সাথে সম্পর্কিত নয়। মূল পোস্টার সমস্যার ES6 'async / প্রতীক্ষার সাথে কোন সম্পর্ক নেই। ECMAScript 2017 এ এই নতুন সিনট্যাকটিক চিনির প্রবর্তনের আগে প্রতিশ্রুতিগুলি বিদ্যমান ছিল এবং তারা প্রতিশ্রুতিগুলি "হুডের নীচে" ব্যবহার করেছিল। Async / অপেক্ষায় MDN দেখুন ।
অবশেষে ২

ES8 / নোডেজের জন্য, আপনি যদি অ্যাসিঙ্ক awaitফাংশনের বাইরে ব্যবহার করেন তবে ত্রুটিগুলি ছুঁড়ে দেওয়া হয়। সম্ভবত এখানে সর্বোত্তম উদাহরণটি হবে AuthUserফাংশনটি করা async, তারপরে এটি শেষ হবেreturn await google.login(...);
জন এল।

4

thenপদ্ধতি একটি মুলতুবি প্রতিশ্রুতি যা কলে নিবন্ধিত ফলে হ্যান্ডলার ফেরত মান দ্বারা অ্যাসিঙ্ক্রোনাস সমাধান করা যেতে পারে ফেরৎ then, অথবা হ্যান্ডলার বলা ভিতরে একটি ত্রুটি ছুঁড়ে প্রত্যাখ্যাত।

সুতরাং কলিংটি AuthUserহঠাৎ করে ব্যবহারকারীকে সিঙ্ক্রোনসিজে লগ করবে না, তবে এমন একটি প্রতিশ্রুতি দেয় যা লগইন সফল হওয়ার পরে (বা ব্যর্থ হয়) এর পরে নিবন্ধিত হ্যান্ডলারদের ডাকা হবে। আমি thenলগইন প্রতিশ্রুতির একটি ধারা দ্বারা সমস্ত লগইন প্রসেসিং ট্রিগার করার পরামর্শ দেব । EG প্রবাহের ক্রমটি হাইলাইট করার জন্য নামযুক্ত ফাংশনগুলি ব্যবহার করে:

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

প্রতিশ্রুতিগুলিতে MDN বিভাগ দেখুন বিশেষত, তারপরে () এর রিটার্নের ধরণটি দেখুন

লগ ইন করতে, ব্যবহারকারী-এজেন্টকে সার্ভারে একটি অনুরোধ জমা দিতে হবে এবং প্রতিক্রিয়া পাওয়ার জন্য অপেক্ষা করতে হবে। যেহেতু আপনার অনুরোধটি রাউন্ড-ট্রিপ চলাকালীন সম্পূর্ণরূপে কার্যকর করা বন্ধ করে দেয় তা সাধারণত খারাপ ব্যবহারকারীর অভিজ্ঞতা অর্জন করে, কার্যত প্রতিটি জেএস ফাংশন যা আপনাকে লগ ইন করে (বা সার্ভারের ইন্টারঅ্যাকশনটির অন্য কোনও রূপ সম্পাদন করে) একটি প্রতিশ্রুতি ব্যবহার করে বা এর মতো খুব বেশি কিছু ব্যবহার করে will , অ্যাসিঙ্ক্রোনালি ফলাফল বিতরণ।

এখন, এও লক্ষ্য করুন যে returnবিবৃতিগুলি সর্বদা তাদের উপস্থিত ফাংশনের প্রসঙ্গে মূল্যায়ন করা হয় So সুতরাং আপনি যখন লিখেছেন:

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()এমন একটি ফাংশন হওয়া দরকার যা টোকনকে আসলে কোনওভাবে পরিচালনা করে।


@ এসসিআর আমি উত্তরটি প্রশ্নকর্তা পরিষ্কার করার আগেই লিখেছিলেন যে তারা সিঙ্ক্রোনালিভাবে কোনও মূল্য ফেরত দেওয়ার উপায় খুঁজছেন এবং কোড স্নিপেটের দ্বারা অনুমান করা যায় তার বাইরে তাদের দেব পরিবেশ বা ভাষার সংস্করণ সম্পর্কে অনুমান করা ছাড়াই - এটি নিরাপদ ES6 ধরে নিতে, তবে প্রয়োজন ES7 নয়।
জেসি আমানো

@ আহমাদবামিহ ঠিক আছে, করবে। আমি সমস্যাটি ধরে নিচ্ছি যে আমি returnনতুন (ইশ) ক্লোজার সিনট্যাক্সের সাথে কীভাবে আচরণ করা হয় তা ভুল বুঝেছি , এক্ষেত্রে - ভাল, আমি দৃ strongly়ভাবে এটি অস্বীকার করি, তবে ত্রুটিটি এখনও আমার এবং আমি এর জন্য ক্ষমা চাইছি।
জেসি আমানো

2
@ আহমাদবামিহ এর, আমি আসলে সেই অংশটিই জানতাম, এজন্য আমি দৃserted়ভাবে দাবি করেছিলাম যে 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, অতএব পদ্ধতিটি কল কিছুই করে না এবং কোডটি সহজ করার জন্য এবং পাঠযোগ্যতা বাড়ানোর জন্য বাদ দেওয়া উচিত - একটি বিবৃতি যা সম্পূর্ণ সত্য।
বার্গি

0

আপনার প্রতিশ্রুতি মুলতুবি রয়েছে, এটি দ্বারা সম্পূর্ণ করুন

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

আপনার অবশিষ্ট কোড পরে। এই সমস্ত কোডটি হ'ল এটি .then()আপনার প্রতিশ্রুতি পূর্ণ করে এবং কনসোলে ফলাফলের পরিবর্তনশীল এবং মুদ্রণের ফলাফলের শেষ ফলাফলটি ক্যাপচার করে । মনে রাখবেন, আপনি বিশ্বব্যাপী চলকের ফলাফল সংরক্ষণ করতে পারবেন না। আশা করি ব্যাখ্যাটি আপনাকে সহায়তা করতে পারে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.