নতুন প্রতিশ্রুতি () কনস্ট্রাক্টরের অভ্যন্তরে async ব্যবহার / প্রতীক্ষা করা কি কোনও এন্টি-প্যাটার্ন?


93

আমি async.eachLimitএকবারে সর্বাধিক সংখ্যক ক্রিয়াকলাপ নিয়ন্ত্রণ করতে ফাংশনটি ব্যবহার করছি ।

const { eachLimit } = require("async");

function myFunction() {
 return new Promise(async (resolve, reject) => {
   eachLimit((await getAsyncArray), 500, (item, callback) => {
     // do other things that use native promises.
   }, (error) => {
     if (error) return reject(error);
     // resolve here passing the next value.
   });
 });
}

আপনি দেখতে পাচ্ছেন, আমি myFunctionফাংশনটিকে অ্যাসিঙ্ক হিসাবে ঘোষণা করতে পারি না কারণ ফাংশনের দ্বিতীয় কলব্যাকের ভিতরে মানটির আমার অ্যাক্সেস নেই eachLimit


"যেমন আপনি দেখতে পাচ্ছেন, আমি মাই ফাংশনটিকে async হিসাবে ঘোষণা করতে পারি না" --- আপনি কি আরও বিস্তারিত বলতে পারবেন?
zerkms

4
ওহ, ঠিক আছে ... দুঃখিত। আমার কনস্ট্রাক্টর দরকার কারণ আমার একবারে 500 টিরও বেশি অ্যাসিনক্রোনাস অপারেশন এড়াতে async.eachLimit দরকার। আমি পাঠ্য ফাইলগুলি থেকে ডেটা ডাউনলোড এবং আহরণ করছি এবং আমি অনেকগুলি অ্যাসিনক্রোনাস অপারেশনগুলি এড়াতে চাই, ডেটা উত্তোলনের পরে, আমাকে অবশ্যই ডেটা সহ একটি প্রতিশ্রুতি ফিরিয়ে দিতে হবে, এবং আমি এ্যাসিঙ্কের কলব্যাক থেকে ফিরে আসতে সক্ষম হবো না। ।

1. আপনার অপেক্ষার দরকার কেন? অ্যাসিঙ্ক ইতিমধ্যে একটি নিয়ন্ত্রণ-প্রবাহ প্রক্রিয়া। ২. আপনি যদি নোড.জেসের ভিতরে প্রতিশ্রুতি সহ async.js ব্যবহার করতে চান তবে async-q একবার দেখুন
slebetman

কলব্যাক জাহান্নাম এড়াতে এবং যদি কিছু ছুঁড়ে মারে তবে বাইরের প্রতিশ্রুতি ধরা পড়বে।

উত্তর:


81

আপনি প্রতিশ্রুতিবদ্ধ কনস্ট্রাক্টর এক্সিকিউটর ফাংশনের অভ্যন্তরে প্রতিশ্রুতি কার্যকরভাবে ব্যবহার করছেন, সুতরাং এটি প্রতিশ্রুতিবদ্ধ কনস্ট্রাক্টর অ্যান্টি-প্যাটার্ন

আপনার কোডটি মূল ঝুঁকির একটি ভাল উদাহরণ: সমস্ত ত্রুটিগুলি নিরাপদে প্রচার না করে। কেন সেখানে পড়ুন

তদ্ব্যতীত async/ এর ব্যবহার awaitএকই ফাঁদগুলিকে আরও অবাক করে তোলে। তুলনা করা:

let p = new Promise(resolve => {
  ""(); // TypeError
  resolve();
});

(async () => {
  await p;
})().catch(e => console.log("Caught: " + e)); // Catches it.

একটি নিষ্পাপ (ভুল) asyncসমতুল্য:

let p = new Promise(async resolve => {
  ""(); // TypeError
  resolve();
});

(async () => {
  await p;
})().catch(e => console.log("Caught: " + e)); // Doesn't catch it!

আপনার ব্রাউজারের ওয়েব কনসোলটি সর্বশেষের জন্য দেখুন।

প্রথমটি কাজ করে কারণ প্রতিশ্রুতিবদ্ধ কনস্ট্রাক্টর এক্সিকিউটর ফাংশনে যে কোনও তাত্ক্ষণিক ব্যতিক্রম সুনির্দিষ্টভাবে নবনির্মিত প্রতিশ্রুতি প্রত্যাখ্যান করে (তবে কোনওটির ভিতরে .thenআপনি নিজেরাই আছেন)।

দ্বিতীয়টি কাজ করে না কারণ কোনও asyncফাংশনে কোনও তাত্ক্ষণিক ব্যতিক্রম নিজেই ফাংশন দ্বারা প্রত্যাবর্তিত প্রতিশ্রুতিasync প্রত্যাখ্যান করে

যেহেতু কোনও প্রতিশ্রুতি প্রদানকারী নির্বাহকের ফাংশনের রিটার্ন মান অব্যবহৃত, এটি খারাপ খবর!

তোমার গোপন সংকেত

কোন কারণে আপনি সংজ্ঞায়িত না পারে myFunctionযেমন async:

async function myFunction() {
  let array = await getAsyncArray();
  return new Promise((resolve, reject) => {
    eachLimit(array, 500, (item, callback) => {
      // do other things that use native promises.
    }, error => {
      if (error) return reject(error);
      // resolve here passing the next value.
    });
  });
}

তবুও কেন আপনি যখন পুরানো সম্মতি নিয়ন্ত্রণ লাইব্রেরি ব্যবহার করবেন await?


12
আপনার প্রয়োজন নেই return await: return new Promiseযথেষ্ট।
একাকী দিন

4
আমি আনুষ্ঠানিকভাবে এই উত্তরটি অনুমোদন করেছি, আমি ঠিক একই কথাটি বলেছি :-)
বার্গি

4
@celoxxx এখানে দেখুন । আপনার সত্যই কখনও প্রতিশ্রুতি দিয়ে async.js ব্যবহার করা উচিত নয়
বার্গি

4
@celoxxx কেবল প্রকারগুলি ফেলে দিন এবং এটি সরল জেএস হয়ে যায়। আপনার async.js ব্যবহার করা উচিত নয় কারণ বিভিন্ন ইন্টারফেস - নোড-স্টাইল কলব্যাক্স বনাম প্রতিশ্রুতি - খুব বেশি ঘর্ষণ করে এবং অপ্রয়োজনীয় জটিল এবং ত্রুটি-প্রবণ কোডের দিকে পরিচালিত করে।
বার্গি

4
আমি আপনার সাথে একমত ... তবে এই কোডটি পুরানো, এবং আমি ইভেন্টগুলি + async.js ব্যবহার করার জন্য রিফ্যাক্টর করছি (তবুও সীমাবদ্ধতার সীমাটি নিয়ন্ত্রণ করতে। আপনি যদি আরও ভাল উপায় জানেন তবে দয়া করে বলুন)।

16

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

const operation1 = Promise.resolve(5)
const operation2 = Promise.resolve(15)
const publishResult = () => Promise.reject(`Can't publish`)

let p = new Promise((resolve, reject) => {
  (async () => {
    try {
      const op1 = await operation1;
      const op2 = await operation2;

      if (op2 == null) {
         throw new Error('Validation error');
      }

      const res = op1 + op2;
      const result = await publishResult(res);
      resolve(result)
    } catch (err) {
      reject(err)
    }
  })()
});

(async () => {
  await p;
})().catch(e => console.log("Caught: " + e));
  1. ফাংশনটি পাস হয়েছে Promiseকনস্ট্রাক্টরকে দেওয়া অ্যাসিঙ্ক নয়, সুতরাং লটারগুলি ত্রুটিগুলি দেখায় না।
  2. সমস্ত async ফাংশন ব্যবহার করে ক্রমানুসারে কল করা যেতে পারে await
  3. অসম্পূর্ণ ক্রিয়াকলাপগুলির ফলাফলগুলি বৈধ করতে কাস্টম ত্রুটিগুলি যুক্ত করা যেতে পারে
  4. ত্রুটিটি শেষ পর্যন্ত দুর্দান্তভাবে ধরা পড়ে।

যদিও একটি অসুবিধা হ'ল আপনাকে try/catchএটি স্থাপন এবং সংযুক্ত করার কথা মনে রাখতে হবে reject


4
static getPosts(){
    return new Promise( (resolve, reject) =>{
        try {
            const res =  axios.get(url);
            const data = res.data;
            resolve(
                data.map(post => ({
                    ...post,
                    createdAt: new Date(post.createdAt)
                }))
            )
        } catch (err) {
            reject(err);                
        }
    })
}

অপেক্ষার অপসারণ এবং async এই সমস্যাটি সমাধান করবে। কারণ আপনি প্রতিশ্রুতি বস্তু প্রয়োগ করেছেন, এটি যথেষ্ট।


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