কীভাবে অসিনক / প্রতীক সিনট্যাক্সে প্রত্যাখ্যান করবেন?


282

অ্যাসিঙ্ক / প্রতীক্ষিত কার্য দ্বারা প্রত্যাশিত প্রতিশ্রুতি আমি কীভাবে প্রত্যাখ্যান করতে পারি?

উদাহরণস্বরূপ

foo(id: string): Promise<A> {
  return new Promise((resolve, reject) => {
    someAsyncPromise().then((value)=>resolve(200)).catch((err)=>reject(400))
  });
}

অ্যাসিঙ্ক / অপেক্ষায় অনুবাদ করুন

async foo(id: string): Promise<A> {
  try{
    await someAsyncPromise();
    return 200;
  } catch(error) {//here goes if someAsyncPromise() rejected}
    return 400; //this will result in a resolved promise.
  });
}

সুতরাং, আমি কীভাবে এই ক্ষেত্রে এই প্রতিশ্রুতি সঠিকভাবে প্রত্যাখ্যান করতে পারি?


20
Promiseকনস্ট্রাক্টর এন্টিপ্যাটার্ন এড়িয়ে চলুন ! এমনকি প্রথম স্নিপেটটি লেখা উচিত ছিলfoo(id: string): Promise<A> { return someAsyncPromise().then(()=>{ return 200; }, ()=>{ throw 400; }); }
বার্গি

10
আমি মনে করি যে এই প্রশ্নের কোডটি ভ্যানিলা জেএস-তে অনুবাদ করা সহায়ক হবে, কারণ টাইপস্ক্রিপ্টের সাথে প্রশ্নের কোনও যোগসূত্র নেই। আমি যদি তা করে থাকি তবে কী সম্পাদনাটি সম্ভবত গ্রহণযোগ্য হবে?
জ্যাকব ফোর্ড

উত্তর:


326

আপনার সেরা বাজি হয় throwএকটি Errorমোড়ানো মান, একটি সঙ্গে একটি প্রত্যাখ্যাত প্রতিশ্রুতি যা ফলাফল Errorমোড়ানো মান:

} catch (error) {
    throw new Error(400);
}

আপনি কেবল throwমানটিও করতে পারেন তবে তারপরে কোনও স্ট্যাক ট্রেসের তথ্য নেই:

} catch (error) {
    throw 400;
}

পর্যায়ক্রমে, Errorমান মোড়ানো দিয়ে প্রত্যাখ্যানিত প্রতিশ্রুতি ফিরিয়ে দিন , তবে এটি মূর্খতা নয়:

} catch (error) {
    return Promise.reject(new Error(400));
}

(বা শুধু return Promise.reject(400); , তবে আবার কোনও প্রসঙ্গের তথ্য নেই))

(আপনার ক্ষেত্রে, আপনি যেমন ব্যবহার করছেন TypeScriptএবং fooএর পুনরুদ্ধার মানটি আপনি ব্যবহার করছেন Promise<A>, তেমনইreturn Promise.reject<A>(400 /*or error*/); )

একটি async/ এawait পরিস্থিতিতে পরিস্থিতিতে, এটি শেষ সম্ভবত একটি শব্দার্থবিজ্ঞান ভুল ম্যাচ কিছুটা, কিন্তু এটি কাজ করে।

যদি আপনি একটি নিক্ষেপ করেন Error, যা সিনট্যাক্সের fooসাথে আপনার ফলাফলকে গ্রাস করে এমন কিছু নিয়ে ভাল খেলে await:

try {
    await foo();
} catch (error) {
    // Here, `error` would be an `Error` (with stack trace, etc.).
    // Whereas if you used `throw 400`, it would just be `400`.
}

12
এবং যেহেতু অ্যাসিঙ্ক / প্রতীক্ষা অ্যাসিঙ্ক প্রবাহটিকে সিঙ্ক সিনট্যাক্সে ফিরিয়ে নেওয়া, আইএমওর throwচেয়ে ভাল Promise.reject()throw 400অন্য একটি প্রশ্ন কিনা । ওপিতে এটি 400 টি প্রত্যাখ্যান করছে এবং আমরা যুক্তি দিতে পারি যে এটির Errorপরিবর্তে এটি প্রত্যাখ্যান করা উচিত ।
ইউনিয়ন

2
হ্যাঁ, তবে, যদি আপনার কোড চেনটি সত্যই অ্যাসিঙ্ক ব্যবহার করে / অপেক্ষা করে থাকে, তবে আপনি ..... এখানে কঠিন টাইপ করতে আমাকে উত্তর হিসাবে ডেমো করতে দিন
ইউনিয়ন

1
ক্যাচ ব্লকে আপনাকে দেওয়া ত্রুটির বিপরীতে কোনও নতুন ত্রুটি নিক্ষেপ করতে চান এমন কোনও কারণ আছে কি?
অ্যাড্রিয়ান এম

1
@ সেবাস্তিয়ান - সেখানে আপনি কী বোঝাতে চেয়েছেন তা আমি জানি না। ইন asyncফাংশন, কিছু নেই resolveবা rejectফাংশন। আছে returnএবং throwযা সমাধান করতে কথ্য উপায় আছে ও অস্বীকার করবেন asyncফাংশনের প্রতিশ্রুতি।
টিজে ক্রাউডার

1
@ জান-ফিলিপ জিহরস্কে - আপনি পারেন তবে আমি কখনই তা করতে পারি না। এটি একটি উদাহরণ তৈরি করছে, newতা স্পষ্ট করে তোলে। আরও মনে রাখবেন যে আপনার যদি একটি Errorসাবক্লাস ( class MyError extends Error) থাকে তবে আপনি এটি ছেড়ে দিতে পারবেন না ...
টিজে ক্রাউডার

146

এটি সম্ভবত উল্লেখ করা উচিত যে আপনি catch()আপনার অ্যাসিঙ্ক অপারেশন কল করার পরে কেবল কোনও ফাংশন চেইন করতে পারেন কারণ হুডের নীচে এখনও একটি প্রতিশ্রুতি ফিরে আসে।

await foo().catch(error => console.log(error));

আপনি try/catchযদি সিনট্যাক্সটি পছন্দ না করেন তবে এড়াতে পারবেন ।


1
সুতরাং আমি যদি আমার asyncফাংশনটি প্রত্যাখ্যান করতে চাই তবে আমি ব্যতিক্রম ছুঁড়ে ফেলি এবং তারপরে .catch()আমি ফিরে আসি Promise.rejectবা ফোন করি ঠিক তেমনভাবে এটি ধরতে পারি reject। আমি এটা পছন্দ করি!
icl7126

7
কেন এটি গ্রহণযোগ্য উত্তর হওয়া উচিত তা আমি বুঝতে পারি না। কেবল স্বীকৃত উত্তর ক্লিনারই নয়, এটি awaitএকটি রুটিনে সমস্ত সম্ভাব্য ব্যর্থতাও পরিচালনা করে । প্রত্যেকের জন্য খুব সুনির্দিষ্ট মামলার প্রয়োজন awaitনা হলে আমি কেন দেখতে পাচ্ছি না আপনি কেন এগুলি তাদের ধরতে চান। শুধু আমার বিনীত মতামত।
edgaralienfoe

1
আমার ব্যবহারের ক্ষেত্রে @ জাবেসস, ​​কেবল প্রতিটি awaitব্যর্থতা আলাদাভাবে ধরার দরকার ছিল না , তবে প্রতিশ্রুতি ভিত্তিক কাঠামোর সাথে কাজ করারও দরকার ছিল যা প্রতিশ্রুতিগুলি ত্রুটিযুক্ত করে প্রত্যাখ্যান করেছিল।
করাসিক

এটি আমার পক্ষে কাজ করে না। Url ব্যর্থ হলে ক্যাচ ব্লকে যাচ্ছে বলে মনে হচ্ছে না। [প্রতিক্রিয়া] = অপেক্ষায় রয়েছেন oauthGet ( ${host}/user/permissions/repositories_wrong_url/, accessToken, accessTokenSecret) .catch (মাত্রই ভুল করে => {logger.error (মাত্রই ভুল করে) 'সংগ্রহস্থলের অনুমতি পেতে অক্ষম'; কলব্যাক (মাত্রই ভুল করে);})
sn.anurag

1
awaitএখানে কিওয়ার্ডের দরকার নেই।
আশীষ রাওয়াত

12

আপনি একটি মোড়ক ফাংশন তৈরি করতে পারেন যা প্রতিশ্রুতি গ্রহণ করে এবং কোনও ত্রুটি না হলে ডেটা সহ একটি অ্যারের এবং কোনও ত্রুটি থাকলে ত্রুটি প্রদান করে।

function safePromise(promise) {
  return promise.then(data => [ data ]).catch(error => [ null, error ]);
}

ভালো এটি ব্যবহার করুন ES7 এবং একটি ইন ASYNC ফাংশন:

async function checkItem() {
  const [ item, error ] = await safePromise(getItem(id));
  if (error) { return null; } // handle error and return
  return item; // no error so safe to use item
}

1
দেখতে অনেকটা কমনীয়তা ছাড়াই সুদৃশ্য গো সিনট্যাক্স রাখার চেষ্টা বলে মনে হচ্ছে। আমি কোডটি এটি ব্যবহার করে সমাধানের বাইরে থাকা মানটি স্তন্যপান করার জন্য পর্যাপ্ত পরিমাণে বিস্মৃত হয়ে খুঁজে পেয়েছি।
কিম

8

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

async foo(id: string): Promise<A> {
    return new Promise(function(resolve, reject) {
        // execute some code here
        if (success) { // let's say this is a boolean value from line above
            return resolve(success);
        } else {
            return reject(error); // this can be anything, preferably an Error object to catch the stacktrace from this function
        }
    });
}

তারপরে আপনি কেবল ফিরে আসা প্রতিশ্রুতি অনুসারে পদ্ধতিগুলি চেইন করুন:

async function bar () {
    try {
        var result = await foo("someID")
        // use the result here
    } catch (error) {
        // handle error here
    }
}

bar()

উত্স - এই টিউটোরিয়াল:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise


5
প্রশ্নটি বিশেষত async / অপেক্ষার বিষয়ে জিজ্ঞাসা করেছিল। প্রতিশ্রুতি ব্যবহার করা হচ্ছে না
মক

এই উত্তরটি নির্দিষ্ট সঠিক উত্তর হিসাবে বোঝানো হয়নি। এটি উপরে বর্ণিত অন্যান্য উত্তরের একটি সমর্থন উত্তর ছিল। আমি এটি একটি মন্তব্য হিসাবে লিখতে হবে কিন্তু আমার কোড আছে যে দেওয়া, উত্তর ক্ষেত্র একটি ভাল জায়গা।
ওজজি দ্য জায়ান্ট

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

আপনার প্রতিক্রিয়াটি আপডেট করার জন্য আমি এটি সম্পাদনা করেছি। যদি আমি কিছু মিস করি তবে আমাকে জানান
মক

4

আমার কাছে একাধিক চেষ্টা-ব্লক না করে কোনও অভিনব পদ্ধতির মাধ্যমে প্রত্যাখ্যানগুলি সঠিকভাবে পরিচালনা করার জন্য আমার একটি পরামর্শ রয়েছে ।

import to from './to';

async foo(id: string): Promise<A> {
    let err, result;
    [err, result] = await to(someAsyncPromise()); // notice the to() here
    if (err) {
        return 400;
    }
    return 200;
}

কোথায় to.ts ফাংশন থেকে আমদানি করা হবে:

export default function to(promise: Promise<any>): Promise<any> {
    return promise.then(data => {
        return [null, data];
    }).catch(err => [err]);
}

ক্রেডিটগুলি নিম্নলিখিত লিঙ্কে ডিমা গ্রসম্যানের কাছে যায় ।


1
আমি এই নির্মাণটি প্রায় একচেটিয়াভাবে (অনেকগুলি ক্লিনার) ব্যবহার করি এবং একটি 'টু' মডিউল রয়েছে যা কিছুক্ষণের জন্য এনএমপিজেএস / প্যাকেজ / বায়েট- টু- জাজের জন্য ছিল । পৃথক ঘোষণাপত্রের দরকার নেই কেবল ডিকনস্ট্রাক্ট করা অ্যাসাইনমেন্টের সামনে। এছাড়াও let [err]=শুধুমাত্র ত্রুটি পরীক্ষা করা হলে তা করতে পারে।
ডিসিবলার

3

এটি @ টিজে ক্রাউডারের একটির উত্তর নয়। কেবলমাত্র একটি মন্তব্যে প্রতিক্রিয়া জানিয়ে একটি মন্তব্য "এবং আসলে, যদি ব্যতিক্রমটিকে প্রত্যাখাতে রূপান্তরিত করা হয় তবে আমি নিশ্চিত নই যে আমি আসলেই এটির ত্রুটি হলে বিরক্ত করছি কিনা। কেবল ত্রুটি ছুঁড়ে দেওয়ার জন্য আমার কারণগুলি সম্ভবত প্রয়োগ হয় না। "

যদি আপনার কোড ব্যবহার করছে async/ await, তাহলে এটি এখনও একটি সঙ্গে প্রত্যাখ্যান করার একটি ভাল অনুশীলন Errorপরিবর্তে 400:

try {
  await foo('a');
}
catch (e) {
  // you would still want `e` to be an `Error` instead of `400`
}

3

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

আমি কেবল চুলের বিভাজনই করছি না তা নিশ্চিত করার জন্য, এই কোডটি ব্যবহার করে আমি সেখানে তিনটি ভিন্ন পদ্ধতির একটি পারফরম্যান্স পরীক্ষা চালিয়েছি:

const iterations = 100000;

function getSwitch() {
  return Math.round(Math.random()) === 1;
}

function doSomething(value) {
  return 'something done to ' + value.toString();
}

let processWithThrow = function () {
  if (getSwitch()) {
    throw new Error('foo');
  }
};

let processWithReturn = function () {
  if (getSwitch()) {
    return new Error('bar');
  } else {
    return {}
  }
};

let processWithCustomObject = function () {
  if (getSwitch()) {
    return {type: 'rejection', message: 'quux'};
  } else {
    return {type: 'usable response', value: 'fnord'};
  }
};

function testTryCatch(limit) {
  for (let i = 0; i < limit; i++) {
    try {
      processWithThrow();
    } catch (e) {
      const dummyValue = doSomething(e);
    }
  }
}

function testReturnError(limit) {
  for (let i = 0; i < limit; i++) {
    const returnValue = processWithReturn();
    if (returnValue instanceof Error) {
      const dummyValue = doSomething(returnValue);
    }
  }
}

function testCustomObject(limit) {
  for (let i = 0; i < limit; i++) {
    const returnValue = processWithCustomObject();
    if (returnValue.type === 'rejection') {
      const dummyValue = doSomething(returnValue);
    }
  }
}

let start, end;
start = new Date();
testTryCatch(iterations);
end = new Date();
const interval_1 = end - start;
start = new Date();
testReturnError(iterations);
end = new Date();
const interval_2 = end - start;
start = new Date();
testCustomObject(iterations);
end = new Date();
const interval_3 = end - start;

console.log(`with try/catch: ${interval_1}ms; with returned Error: ${interval_2}ms; with custom object: ${interval_3}ms`);

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

আমার ফলাফলগুলি ছিল:

with try/catch: 507ms; with returned Error: 260ms; with custom object: 5ms

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

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


2
এছাড়াও, মনে রাখবেন যে কোনও অ্যাসিঙ্ক ফাংশনটির মধ্যে অপ্রত্যাশিত ত্রুটিগুলি পরিচালনা করার বিষয়ে আপনাকে চাপ দেওয়ার দরকার নেই যদি সেই ফাংশনটিতে কলটি ঘেরের মধ্যে থাকা চেষ্টা / ধরার ব্লকের মধ্যে থাকে - প্রতিশ্রুতির বিপরীতে - অ্যাসিঙ্ক ফাংশনগুলি তাদের নিক্ষিপ্ত ত্রুটিগুলিকে বুদবুদ করে দেয় এনকোলেসিং স্কোপ, যেখানে তারা ঠিক সেই সুযোগে স্থানীয় ত্রুটির মতো পরিচালনা করা হয়। এটি async / অপেক্ষা করার অন্যতম প্রধান সুবিধা!
RiqueW

মাইক্রোবেঞ্চমার্কস শয়তান are সংখ্যার কাছাকাছি তাকান। আপনার এখানে 1 মিমের পার্থক্যটি লক্ষ্য করতে 1000x কিছু করা দরকার। হ্যাঁ, থ্রোক / ক্যাচ যুক্ত করা ফাংশনটিকে ডিপ্টিভাইজ করবে। তবে ক) আপনি যদি অ্যাসিঙ্কের জন্য অপেক্ষা করছেন তবে ব্যাকগ্রাউন্ডে এটি বেশিরভাগ অর্ডারের প্রশস্ততা নিতে 0.0005 মেসের বেশি সময় লাগবে। খ) আপনার এখানে 1 মিমি পার্থক্য করতে 1000x করা উচিত।
জেমি পেট
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.