অ্যাসিঙ্কের সাথে ব্লকগুলি ধরুন / অপেক্ষা করুন


116

আমি নোড as এ্যাসিঙ্ক / অপেক্ষার বৈশিষ্ট্যটি খনন করছি এবং এই জাতীয় কোড জুড়ে হোঁচট খাচ্ছি

function getQuote() {
  let quote = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
  return quote;
}

async function main() {
  try {
    var quote = await getQuote();
    console.log(quote);
  } catch (error) {
    console.error(error);
  }
}

main();

এটি একমাত্র সম্ভাবনা হিসাবে সমাধান / প্রত্যাখ্যান বা প্রত্যাবর্তন / ছুঁড়ে async / প্রতীক্ষার সাথে প্রত্যাশা বলে মনে হচ্ছে, তবে, ভি 8 চেষ্টা / ক্যাচ ব্লকের মধ্যে কোডটি অনুকূলিত করে না ?!

বিকল্প আছে?


'অপেক্ষার পরে নিক্ষেপ করা সফল হয় না' এর অর্থ কী? ভুল হলে? যদি তা প্রত্যাশিত ফলাফল না ফেরায়? আপনি ক্যাচ ব্লকে পুনর্বিবেচনা করতে পারেন।
ডেভিডিগ

আফাইক ভি 8 চেষ্টা করুন / ধরুন, একটি নিক্ষেপ বিবৃতি ধীর একটি
তামাস হেগেডাস

1
আমি এখনও প্রশ্ন বুঝতে পারি না। আপনি পুরানো প্রতিশ্রুতিবদ্ধ শৃঙ্খলা ব্যবহার করেন না, তবে আমার মনে হয় না এটি আরও দ্রুত হবে। তাহলে আপনি চেষ্টা করে দেখার পারফরম্যান্স সম্পর্কে উদ্বিগ্ন? তারপরে অ্যাসিঙ্কের অপেক্ষায় এটি কী?
তামাস হেজেডাস

আমার উত্তরটি পরীক্ষা করে দেখুন আমি একটি ক্লিনার কাছে যাওয়ার চেষ্টা করেছি
জারডিলিয়র

উত্তর:


133

বিকল্প

এর বিকল্প:

async function main() {
  try {
    var quote = await getQuote();
    console.log(quote);
  } catch (error) {
    console.error(error);
  }
}

স্পষ্টভাবে প্রতিশ্রুতি ব্যবহার করে এমন কিছু হবে:

function main() {
  getQuote().then((quote) => {
    console.log(quote);
  }).catch((error) => {
    console.error(error);
  });
}

বা এই জাতীয় কিছু, ধারাবাহিকতা পাসিং শৈলী ব্যবহার করে:

function main() {
  getQuote((error, quote) => {
    if (error) {
      console.error(error);
    } else {
      console.log(quote);
    }
  });
}

আসল উদাহরণ

আপনার আসল কোডটি যা করে তা হ'ল কার্যকরকরণ স্থগিত করা এবং প্রতিশ্রুতি মীমাংসিত হয়ে ফিরে আসার জন্য অপেক্ষা করুন getQuote()। এরপরে এটি কার্যকর করা চালিয়ে যায় এবং এতে প্রত্যাবর্তিত মানটি লিখে দেয়var quote প্রেরণ করে এবং তারপরে প্রতিশ্রুতিটি সমাধান করা হলে এটি মুদ্রণ করে, বা একটি ব্যতিক্রম ছুঁড়ে দেয় এবং ক্যাপ ব্লকটি চালায় যা প্রতিশ্রুতি প্রত্যাখ্যান করা হলে ত্রুটিটি মুদ্রণ করে।

আপনি দ্বিতীয় উদাহরণের মতো সরাসরি প্রতিশ্রুতি এপিআই ব্যবহার করে একই জিনিসটি করতে পারেন।

কর্মক্ষমতা

এখন, পারফরম্যান্সের জন্য। আসুন এটি পরীক্ষা!

আমি কেবল এই কোডটি লিখেছি - একটি ফেরতের মান হিসাবে f1()দেয় 1, ব্যতিক্রম হিসাবে f2()ছোঁড়ে 1:

function f1() {
  return 1;
}

function f2() {
  throw 1;
}

এখন একই কোডটি মিলিয়ন বার কল করা যাক, এর সাথে প্রথম f1():

var sum = 0;
for (var i = 0; i < 1e6; i++) {
  try {
    sum += f1();
  } catch (e) {
    sum += e;
  }
}
console.log(sum);

এবং তারপরে এর পরিবর্তন f1()করা যাক f2():

var sum = 0;
for (var i = 0; i < 1e6; i++) {
  try {
    sum += f2();
  } catch (e) {
    sum += e;
  }
}
console.log(sum);

এটি আমি পেয়েছি ফলাফল f1:

$ time node throw-test.js 
1000000

real    0m0.073s
user    0m0.070s
sys     0m0.004s

এটিই আমি পেয়েছিলাম f2:

$ time node throw-test.js 
1000000

real    0m0.632s
user    0m0.629s
sys     0m0.004s

দেখে মনে হচ্ছে যে আপনি এক মিলিত থ্রেড প্রক্রিয়াতে 2 মিলিয়ন সেকেন্ড নিক্ষেপ করার মতো কিছু করতে পারেন। আপনি যদি এর থেকে বেশি কাজ করে থাকেন তবে আপনার এটি সম্পর্কে চিন্তা করতে হবে।

সারসংক্ষেপ

আমি নোডের মতো জিনিসগুলি নিয়ে চিন্তা করব না। যদি এর মতো জিনিসগুলি খুব বেশি ব্যবহৃত হয় তবে এটি শেষ পর্যন্ত ভি 8 বা স্পাইডারমোনকি বা চক্র দলগুলি দ্বারা অনুকূলিত হবে এবং প্রত্যেকে অনুসরণ করবে - এটি নীতি হিসাবে অনুকূলিত নয়, এটি কেবল সমস্যা নয় a

এমনকি যদি এটি অপ্টিমাইজড না হয় তবে আমি এখনও তর্ক করব যে আপনি যদি নোডে আপনার সিপিইউটি বের করে নিয়ে থাকেন তবে আপনার সম্ভবত সিতে আপনার নম্বর ক্রাঞ্চিং লিখতে হবে - অন্যান্য জিনিসের মধ্যে নেটিভ অ্যাডোনগুলির জন্য এটি। অথবা নোড.নেটিভের মতো জিনিসগুলি নোড.জেএস এর চেয়ে কাজের জন্য উপযুক্ত হবে maybe

আমি ভাবছি এমন কোনও ব্যবহারের ক্ষেত্রে কী হতে পারে যাতে এতগুলি ব্যতিক্রম ছোঁড়া উচিত। সাধারণত কোনও মান ফেরত দেওয়ার পরিবর্তে ব্যতিক্রম ছুঁড়ে ফেলা ভাল, ব্যতিক্রম।


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

4
@ পেট্রিক "হতে পারে" এবং "হবে" অনুমান এবং আসলে পরীক্ষার মধ্যে পার্থক্য। আমি এটি একটি একক বিবৃতিতে পরীক্ষা করেছি কারণ এটিই আপনার প্রশ্নে ছিল তবে আপনি আমার উদাহরণগুলিকে একাধিক বক্তব্যের জন্য পরীক্ষায় খুব সহজেই রূপান্তর করতে পারেন। অ্যাসিক্রোনাস কোড লেখার জন্য আমি আরও বেশ কয়েকটি অপশন সরবরাহ করেছি যা সম্পর্কে আপনি জিজ্ঞাসা করেছিলেন। যদি এটি আপনার প্রশ্নের উত্তর দেয় তবে আপনি উত্তরটি গ্রহণ করার বিষয়ে বিবেচনা করতে পারেন । এর সংক্ষিপ্তসারটি হিসাবে: অবশ্যই ব্যতিক্রমগুলি রিটার্নের চেয়ে ধীরে ধীরে তবে তাদের ব্যবহারের ব্যতিক্রম হওয়া উচিত।
আরএসপি

1
ব্যতিক্রম নিক্ষেপ করা অবশ্যই একটি ব্যতিক্রম বলে মনে করা হচ্ছে। বলা হচ্ছে, কোডটি আপত্তিহীন, আপনি কোনও ব্যতিক্রম নিক্ষেপ করেন বা না করেন। পারফরম্যান্স হিট ব্যবহার থেকে আসে try catch, ব্যতিক্রম ছোঁড়া থেকে নয়। সংখ্যাগুলি ছোট থাকাকালীন, আপনার পরীক্ষাগুলি অনুসারে এটি প্রায় 10 গুণ কম ধীরে ধীরে, যা তুচ্ছ নয়।
নেপক্সক্স

21

গোলংয়ে হ্যান্ডলিংয়ের ক্ষেত্রে ত্রুটির অনুরূপ বিকল্প

যেহেতু async / প্রতীক্ষা হুডের অধীনে প্রতিশ্রুতি ব্যবহার করে, আপনি এর মতো সামান্য ইউটিলিটি ফাংশন লিখতে পারেন:

export function catchEm(promise) {
  return promise.then(data => [null, data])
    .catch(err => [err]);
}

তারপরে যখনই আপনাকে কিছু ত্রুটি ধরা দরকার তখন এটিকে আমদানি করুন এবং আপনার অ্যাসিঙ্ক ফাংশনটি মোড়ানো করুন যা এটির সাথে প্রতিশ্রুতি দেয়।

import catchEm from 'utility';

async performAsyncWork() {
  const [err, data] = await catchEm(asyncFunction(arg1, arg2));
  if (err) {
    // handle errors
  } else {
    // use data
  }
}

আমি একটি এনপিএম প্যাকেজ তৈরি করেছি যা ঠিক উপরেরটি করে
মাইক

2
@ মাইক আপনি হুইলটি পুনরায় উদ্ভাবন করছেন - ইতিমধ্যে এটি একটি জনপ্রিয় প্যাকেজ রয়েছে যা হুবহু এটি করে: npmjs.com/package/await-to-js
জাকুব কুকুল

21

ট্রাই-ক্যাচ ব্লকের বিকল্প অপেক্ষারত-জেএস লাইব। আমি প্রায়শই এটি ব্যবহার করি। উদাহরণ স্বরূপ:

import to from 'await-to-js';

async function main(callback) {
    const [err,quote] = await to(getQuote());
    
    if(err || !quote) return callback(new Error('No Quote found'));

    callback(null,quote);

}

চেষ্টা করার সাথে তুলনা করার সময় এই সিনট্যাক্সটি অনেক পরিষ্কার er


এটি চেষ্টা করে দেখে ভাল লেগেছিল। একটি নতুন মডিউল ইনস্টল করার ব্যয়ে পরিষ্কার এবং পঠনযোগ্য কোড। তবে আপনি যদি অনেকগুলি অ্যাসিঙ্ক ফাংশন লেখার পরিকল্পনা করছেন তবে আমি বলতে চাই এটি একটি দুর্দান্ত সংযোজন! ধন্যবাদ
ফিলিপবারক

15
async function main() {
  var getQuoteError
  var quote = await getQuote().catch(err => { getQuoteError = err }

  if (getQuoteError) return console.error(err)

  console.log(quote)
}

বিকল্পভাবে আপনি সম্ভাব্য ভার ঘোষণার পরিবর্তে শীর্ষে ত্রুটি ধরে রাখতে পারেন do

if (quote instanceof Error) {
  // ...
}

যদিও এটি টাইপররর বা রেফারেন্স ত্রুটির মতো কিছু ফেলে দিলে কাজ করবে না। আপনি এটি নিশ্চিত করতে পারেন যদিও এটি নিয়মিত ত্রুটি রয়েছে

async function main() {
  var quote = await getQuote().catch(err => {
    console.error(err)      

    return new Error('Error getting quote')
  })

  if (quote instanceOf Error) return quote // get out of here or do whatever

  console.log(quote)
}

এর জন্য আমার পছন্দটি সমস্ত কিছুকে একটি বড় ট্র্যাচ-ক্যাচ ব্লকে মুড়িয়ে ফেলা হয় যেখানে একাধিক প্রতিশ্রুতি তৈরি হচ্ছে এটি বিশেষত যে প্রতিশ্রুতি দিয়েছিল তা ত্রুটিটি পরিচালনা করা জটিল করে তুলবে। বিকল্প হিসাবে একাধিক চেষ্টা-ধরা ব্লক যা আমি সমানভাবে জটিল মনে করি find


8

একটি ক্লিনার বিকল্প নিম্নলিখিত হবে:

প্রতিটি অ্যাসিঙ্ক ফাংশন প্রযুক্তিগতভাবে একটি প্রতিশ্রুতিবদ্ধ হওয়ার কারণে

অপেক্ষা করার সাথে কল করার সময় আপনি ফাংশনে ক্যাচগুলি যুক্ত করতে পারেন

async function a(){
    let error;

    // log the error on the parent
    await b().catch((err)=>console.log('b.failed'))

    // change an error variable
    await c().catch((err)=>{error=true; console.log(err)})

    // return whatever you want
    return error ? d() : null;
}
a().catch(()=>console.log('main program failed'))

ধরার চেষ্টা করার দরকার নেই, কারণ সমস্ত প্রতিশ্রুতি ত্রুটিগুলি পরিচালনা করা হয় এবং আপনার কোনও কোড ত্রুটি নেই, আপনি পিতামাতাকে বাদ দিতে পারেন !!

বলুন আপনি মোঙ্গোদব নিয়ে কাজ করছেন, যদি এখানে কোনও ত্রুটি থাকে তবে আপনি এটিকে র‌্যাপার তৈরি করা বা ট্র্যাচ ক্যাচ ব্যবহার করার চেয়ে কল করে ফাংশনটিতে এটি পরিচালনা করতে পছন্দ করতে পারেন।


আপনার 3 টি ফাংশন রয়েছে। একটি মান পেয়েছে এবং ত্রুটিটি ধরা হচ্ছে, অন্য কোনও ত্রুটি না থাকলে আপনি ফিরে আসবেন এবং অবশেষে একটি কলব্যাক দিয়ে প্রথম ফাংশনে একটি কল এসেছে যাতে এটি ত্রুটি ফিরে পেয়েছে কিনা তা খতিয়ে দেখার জন্য। এগুলি একটি একক "প্রতিশ্রুতি" দিয়ে সমাধান করা হয় then তারপর (সিবি) .ক্যাচ (সিবি) বা ট্রাইচ্যাচ ব্লক।
চিফ কোশি

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

1
প্রশ্নটি ব্যর্থ প্রতিশ্রুতির পরে কার্যকর করার জন্য জিজ্ঞাসা করে না। এখানে আপনি বি এর জন্য অপেক্ষা করুন, তারপরে সি চালান এবং তারা ভুল করে থাকলে ডি ফিরে আসেন। এই ক্লিনার কেমন? সি বি এর জন্য অপেক্ষা করতে হবে তবুও তারা একে অপরের থেকে স্বতন্ত্র। তারা যদি স্বতন্ত্র হয় তবে তারা কেন একসাথে থাকবে তার কারণ আমি দেখতে পাচ্ছি না। যদি তারা একে অপরের উপর নির্ভরশীল হয়ে থাকে তবে আপনি বি ব্যর্থ হলে সি এর কার্যকর করা বন্ধ করতে চান, .tten.catch এর কাজ বা চেষ্টা করুন। আমি ধরে নিই যে তারা কিছুই ফেরেনি এবং কিছু অ্যাসিনক্রোনাস ক্রিয়া সম্পূর্ণরূপে এ এর ​​সাথে সম্পর্কিত নয় কেন তাদের এ্যাসিঙ্ক অপেক্ষা করতে বলা হচ্ছে?
চিফ কোশী

প্রশ্নটি async / অপেক্ষা করার সময় ত্রুটিগুলি পরিচালনা করতে ব্লকগুলি ধরার চেষ্টা করার বিকল্পগুলির সাথে সম্পর্কিত। এখানে উদাহরণটি বর্ণনামূলক হ'ল এটি উদাহরণ ছাড়া কিছুই নয়। এটি একটি ক্রমানুসারে স্বাধীন অপারেশনগুলির স্বতন্ত্র পরিচালনা পরিচালনা দেখায় যা সাধারণত async / অপেক্ষার জন্য ব্যবহৃত হয়। কেন তারা async অপেক্ষার সাথে ডাকা হয়, এটি কীভাবে পরিচালনা করা যায় তা দেখানোর জন্য। এর বর্ণনামূলক ন্যায়বিচারের চেয়েও বেশি।
জারডিলিয়র

2

আমি এইভাবে করতে চাই :)

const sthError = () => Promise.reject('sth error');

const test = opts => {
  return (async () => {

    // do sth
    await sthError();
    return 'ok';

  })().catch(err => {
    console.error(err); // error will be catched there 
  });
};

test().then(ret => {
  console.log(ret);
});

এটি হ্যান্ডলিং ত্রুটির সাথে মিল co

const test = opts => {
  return co(function*() {

    // do sth
    yield sthError();
    return 'ok';

  }).catch(err => {
    console.error(err);
  });
};

কোড খুব সুস্পষ্ট মানুষ নয়, দেখতে আকর্ষণীয় হলেও আপনি সম্পাদনা করতে পারবেন?
জারডিলিয়র

দুর্ভাগ্যজনক যে এই উত্তরের কোনও ব্যাখ্যা নেই কারণ এটি আপনার দ্বারা নির্ধারিত প্রতিটি প্রতিবন্ধকতার চেষ্টা এড়ানোর জন্য দুর্দান্ত উপায় প্রদর্শন করে await!
জিম

0

catchআমার ফ্যাশনটিতে এই অভিজ্ঞতাটি বিপজ্জনক। পুরো স্ট্যাকের মধ্যে ফেলে দেওয়া কোনও ত্রুটি ধরা পড়বে, কেবল এই প্রতিশ্রুতি থেকে ত্রুটি নয় (যা সম্ভবত আপনি চান তা নয়)।

প্রতিশ্রুতির দ্বিতীয় তর্কটি ইতিমধ্যে প্রত্যাখ্যান / ব্যর্থতা কলব্যাক। পরিবর্তে এটি ব্যবহার করা আরও ভাল এবং নিরাপদ।

এটি হ্যান্ডেল করার জন্য আমি এখানে টাইপস্ক্রিপ্ট টাইপসেসফ ওয়ান-লাইনার লিখেছি:

function wait<R, E>(promise: Promise<R>): [R | null, E | null] {
  return (promise.then((data: R) => [data, null], (err: E) => [null, err]) as any) as [R, E];
}

// Usage
const [currUser, currUserError] = await wait<GetCurrentUser_user, GetCurrentUser_errors>(
  apiClient.getCurrentUser()
);
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.