কলব্যাক ফিরে আসার জন্য কীভাবে "অপেক্ষা" করবেন?


100

একটি সাধারণ কলব্যাক ব্যবহার করার সময় যেমন নীচের উদাহরণে:

test() {
  api.on( 'someEvent', function( response ) {
    return response;
  });
}

অ্যাসিঙ্ক / অপেক্ষার জন্য কীভাবে ফাংশনটি পরিবর্তন করা যেতে পারে? বিশেষত, ধরে নিই যে 'সামিউভেন্ট' একবার এবং কেবল একবার কল করার নিশ্চয়তা দেওয়া হয়েছে, আমি ফাংশন টেস্টটি এমন একটি অ্যাসিঙ্ক ফাংশন হিসাবে চাই যা কলব্যাক কার্যকর না হওয়া পর্যন্ত ফিরে আসে না যেমন:

async test() {
  return await api.on( 'someEvent' );
}

4
কেবলমাত্র রেফারেন্সের জন্য, ES7 / ES2016 নির্দিষ্টকরণ চূড়ান্ত করা হয়েছে এবং এতে অ্যাসিঙ্ক / অপেক্ষার অন্তর্ভুক্ত নেই। এই মুহূর্তে এটি মাত্র একটি পর্যায়ের 3 প্রস্তাব
ড্যান প্রিন্স

ওয়েল এটি অবাক - খুব আশা এটি অন্তর্ভুক্ত করা হয়! @ ড্যানপ্রিন্স তথ্যের জন্য ধন্যবাদ
sean2078

উত্তর:


146

async/awaitযাদু নয়। একটি অ্যাসিঙ্ক ফাংশন এমন একটি ফাংশন যা আপনার জন্য প্রতিশ্রুতিগুলিকে মোড়ক করতে পারে, সুতরাং এটির api.on()কাজ করার জন্য আপনাকে কোনও প্রতিশ্রুতি ফিরিয়ে দিতে হবে। এটার মতো কিছু:

function apiOn(event) {
  return new Promise(resolve => {
    api.on(event, response => resolve(response));
  });
}

তারপরে

async function test() {
  return await apiOn( 'someEvent' ); // await is actually optional here
                                      // you'd return a Promise either way.
}

তবে এটিও মিথ্যা, কারণ অ্যাসিঙ্ক ফাংশনগুলিও তাদের প্রতিশ্রুতি ফিরে দেয়, সুতরাং আপনি প্রকৃতপক্ষে মানটি বের করতে যাবেন না test(), বরং একটি মানের প্রতিশ্রুতি, যা আপনি এর মতো ব্যবহার করতে পারেন:

async function whatever() {
  // snip
  const response = await test();
  // use response here
  // snip
}

4
ফাংশনটির একটি সংক্ষিপ্ত সংস্করণ যা প্রতিশ্রুতি দেয়: const apiOn = (event) => new Promise(resolve => api.on(event, resolve));
ফিলিপ প্লেটস

7

এটি বিরক্তিকর যে কোনও সরল সমাধান নেই, এবং return new Promise(...)মোড়কগুলি পলকভাবে, তবে আমি ব্যবহার করে একটি ঠিক কাজ পেয়েছি util.promisify(বাস্তবে এটিও একই মোড়কের কাজ করে, কেবল দেখতে সুন্দর লাগে)।

function voidFunction(someArgs, callback) {
  api.onActionwhichTakesTime(someMoreArgs, (response_we_need) => {
    callback(null, response_we_need);
  });
}

উপরের ফাংশনটি এখনও কিছু ফেরায় না। আমরা এটিকে পাস Promiseকরে responseপাস করে ফিরতে পারি callback:

const util = require('util');

const asyncFunction = util.promisify(voidFunction);

এখন আমরা আসলে awaitকরতে পারি callback

async function test() {
  return await asyncFunction(args);
}

ব্যবহার করার সময় কিছু নিয়ম util.promisify

  • callbackফাংশনের গত যুক্তি করত যে হতে হবেpromisify
  • অনুমিত কলব্যাকটি অবশ্যই ফর্মের মধ্যে থাকতে হবে (err, res) => {...}

মজার বিষয় হ'ল আমাদের callbackআসলে কোনওটি নির্দিষ্টভাবে লেখার দরকার নেই।


3

async / প্রতীক্ষা যাদু। আপনি asPromiseএই ধরণের পরিস্থিতি পরিচালনা করতে একটি ফাংশন তৈরি করতে পারেন :

function asPromise(context, callbackFunction, ...args) {
    return new Promise((resolve, reject) => {
        args.push((err, data) => {
            if (err) {
                reject(err);
            } else {
                resolve(data);
            }
        });
        if (context) {
            callbackFunction.call(context, ...args);
        } else {
            callbackFunction(...args);
        }
    });
}

এবং তারপরে আপনি যখন চান এটি ব্যবহার করুন:

async test() {
    return await this.asPromise(this, api.on, 'someEvent');
}

আরগের সংখ্যা পরিবর্তনশীল।


1

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

clickMe = async (value) => {
  
  // begin to wait till the message gets here;
  let {message, error} = await getMessage(value);
  
  // if error is not null
  if(error)
    return console.log('error occured ' + error);
   
  return console.log('message ' + message);

}

getMessage = (value) => {

  //returning a promise 
  return new Promise((resolve, reject) => {
  
    setTimeout(() => {
      // if passed value is 1 then it is a success
      if(value == 1){
        resolve({message: "**success**", error: null});
      }else if (value == 2){
        resolve({message: null, error: "**error**"});
      }
    }, 1000);
  
  });

}

clickWithTryCatch = async (value) => {

  try{
    //since promise reject in getMessage2 
    let message = await getMessage2(value);
    console.log('message is ' + message);
  }catch(e){
    //catching rejects from the promise
    console.log('error captured ' + e);
  }

}

getMessage2 = (value) => {

  return new Promise((resolve, reject) => {
  
    setTimeout(() => {
      if(value == 1)
        resolve('**success**');
      else if(value == 2)
        reject('**error**'); 
    }, 1000);
  
  });

}
<input type='button' value='click to trigger for a value' onclick='clickMe(1)' />
<br/>
<input type='button' value='click to trigger an error' onclick='clickMe(2)' />
<br/>
<input type='button' value='handling errors with try catch' onclick='clickWithTryCatch(1)'/>
<br/>
<input type='button' value='handling errors with try catch' onclick='clickWithTryCatch(2)'/>

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