সমস্ত প্রতিশ্রুতি সম্পূর্ণ না হওয়া পর্যন্ত অপেক্ষা করুন এমনকি কিছু প্রত্যাখ্যান করা হলেও


404

ধরা যাক আমার একটা সেট আছে Promise রয়েছে যা নেটওয়ার্ক অনুরোধ করছে, যার মধ্যে একটি ব্যর্থ হবে:

// http://does-not-exist will throw a TypeError
var arr = [ fetch('index.html'), fetch('http://does-not-exist') ]

Promise.all(arr)
  .then(res => console.log('success', res))
  .catch(err => console.log('error', err)) // This is executed   

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

যেহেতু Promises.allএটির জন্য কোনও জায়গা ছাড়েন না, কোনও প্রতিশ্রুতি পাঠাগার ব্যবহার না করে এটি পরিচালনা করার জন্য প্রস্তাবিত প্যাটার্নটি কী?


প্রত্যাশিত যে প্রতিশ্রুতিগুলির ফলস্বরূপ অ্যারেতে কী ফিরিয়ে দেওয়া উচিত?
কুবা ওয়াইরোস্টেক

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

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

ড্যান যা ভাগ করেছে তাতে যুক্ত করতে, ব্লুবার্ডের মতো সমস্ত কার্যনির্বাহী / নিষ্পত্তি যেমন কার্যকারিতা "প্রতিবিম্বিত" ফাংশনের মাধ্যমে ব্যবহার করা যেতে পারে।
user3344977

2
@ কলি: হুম, আমি তা মনে করি না। Promise.allযে কোনও প্রতিশ্রুতি প্রত্যাখ্যান করার সাথে সাথে তা প্রত্যাখ্যান করবে, সুতরাং আপনার প্রস্তাবিত প্রতিমাটি গ্যারান্টি দেয় না যে সমস্ত প্রতিশ্রুতি নিষ্পত্তি হয়েছে।
Jörg ডব্লু মিট্টাগ 21

উত্তর:


308

আপডেট, আপনি সম্ভবত অন্তর্নির্মিত নেটিভ ব্যবহার করতে চান Promise.allSettled:

Promise.allSettled([promise]).then(([result]) => {
   //reach here regardless
   // {status: "fulfilled", value: 33}
});

একটি মজাদার ঘটনা হিসাবে, নীচে এই উত্তরটি ভাষাতে সেই পদ্ধতিটি যুক্ত করার আগে শিল্প ছিল:]


অবশ্যই, আপনার কেবল একটি দরকার reflect:

const reflect = p => p.then(v => ({v, status: "fulfilled" }),
                            e => ({e, status: "rejected" }));

reflect(promise).then((v => {
    console.log(v.status);
});

অথবা ইএস 5 সহ:

function reflect(promise){
    return promise.then(function(v){ return {v:v, status: "fulfilled" }},
                        function(e){ return {e:e, status: "rejected" }});
}


reflect(promise).then(function(v){
    console.log(v.status);
});

বা আপনার উদাহরণে:

var arr = [ fetch('index.html'), fetch('http://does-not-exist') ]

Promise.all(arr.map(reflect)).then(function(results){
    var success = results.filter(x => x.status === "fulfilled");
});

3
আমি মনে করি এটি একটি দুর্দান্ত সমাধান। একটি সহজ বাক্য গঠন অন্তর্ভুক্ত করতে আপনি কি এটি সংশোধন করতে পারেন? ইস্যুটির ত্রুটিটি হ'ল যদি আপনি সাব-প্রতিশ্রুতিগুলিতে ত্রুটিগুলি পরিচালনা করতে চান তবে আপনার সেগুলি ধরা উচিত এবং ত্রুটিটি ফিরিয়ে দেওয়া উচিত। সুতরাং উদাহরণস্বরূপ: gist.github.com/nhagen/a1d36b39977822c224b8
নাথান হেগেন

3
@ নাথানহাগেন এটি আপনাকে পুনরায় ব্যবহারযোগ্য অপারেটরের কাছে কী প্রত্যাখ্যান করেছে এবং কোনটি পূরণ করেছে এবং সমস্যাটি নিষ্কাশন করেছে তা নির্ধারণ করতে দেয়।
বেনজামিন গ্রুইনবাউম

4
আমার নিজের ইস্যুটির জবাবে আমি নিম্নলিখিত এনপিএম প্যাকেজটি তৈরি করেছি: github.com/Bucabug/promise-reflect npmjs.com/package/promise-reflect
SamF

2
আমি কিছুক্ষণ আগে এই সমস্যা একটি গাড়ীতে আঘাত এবং আমি তা এই npm প্যাকেজ তৈরি করা হয়েছে: npmjs.com/package/promise-all-soft-fail
velocity_distance

5
শব্দ reflectকম্পিউটার বিজ্ঞান একটি সাধারণ শব্দ? আপনি দয়া করে এখানে উইকিপিডিয়া বা অন্য কোনও কিছুর মতো ব্যাখ্যা করা হয়েছে তার সাথে লিঙ্ক করতে পারেন। আমি খুব কঠিন অনুসন্ধান করেছিলাম Promise.all not even first rejectকিন্তু "প্রতিচ্ছবি" অনুসন্ধান করতে জানতাম না। ES6 এর এমন Promise.reflectএকটিটি থাকা উচিত যা "প্রতিশ্রুতি.সত্যিক সত্য তবে সমস্ত" এর মতো?
Noitidart

253

অনুরূপ উত্তর, তবে ES6 এর জন্য আরও বুদ্ধিমানের:

const a = Promise.resolve(1);
const b = Promise.reject(new Error(2));
const c = Promise.resolve(3);

Promise.all([a, b, c].map(p => p.catch(e => e)))
  .then(results => console.log(results)) // 1,Error: 2,3
  .catch(e => console.log(e));


const console = { log: msg => div.innerHTML += msg + "<br>"};
<div id="div"></div>

প্রত্যাবর্তিত মানের ধরণের (গুলি) উপর নির্ভর করে ত্রুটিগুলি প্রায়শই সহজেই চিহ্নিত করা যায় (উদাহরণস্বরূপ undefined"যত্ন নেই" এর typeofজন্য ব্যবহার করুন, সরল অ-অবজেক্ট মানগুলির জন্য result.message, result.toString().startsWith("Error:")ইত্যাদি)


1
@ কার্লব্যাটম্যান আমার ধারণা আপনি বিভ্রান্ত অর্ডার ফাংশনগুলি এখানে সমাধান বা প্রত্যাখ্যানের ক্ষেত্রে গুরুত্বপূর্ণ নয় কারণ .map(p => p.catch(e => e))অংশটি সমস্ত প্রত্যাখ্যানগুলিকে সমাধান করা মানগুলিতে রূপান্তরিত করে, তাই Promise.allপৃথক ফাংশনগুলি কতটা সময় নেয় তা নির্বিশেষে সমাধান করে বা প্রত্যাখ্যান করে তা শেষ করার জন্য এখনও অপেক্ষা করে its চেষ্টা করে দেখুন
jib

39
.catch(e => console.log(e));কখনই ডাকা হয় না কারণ এটি কখনই ব্যর্থ হয় না
11

4
@ bfred.it এটি সঠিক correct যদিও প্রতিশ্রুতি শৃঙ্খলাগুলি সমাপ্ত catchকরা সাধারণত ভাল অনুশীলন আইএমএইচও
jib

2
@ সুহেলগুপ্ত এটি ত্রুটিটি ধরা পড়ে eএবং এটিকে একটি নিয়মিত (সাফল্য) মান হিসাবে প্রদান করে। p.catch(function(e) { return e; })শুধুমাত্র খাটো হিসাবে একই । returnঅন্তর্নিহিত হয়।
jib

1
@ জাস্টিনরউজনু ইতিমধ্যে মন্তব্যে আবদ্ধ। আপনি যদি পরে কোড যুক্ত করেন তবে চেইনগুলি সমাপ্ত করার জন্য সর্বদা ভাল অনুশীলন।
jib

71

বেনিয়ামিনের উত্তরটি এই সমস্যাটি সমাধানের জন্য দুর্দান্ত বিমূর্ততা সরবরাহ করে, তবে আমি কম বিমূর্ত সমাধানের জন্য আশা করছিলাম। এই সমস্যাটি সমাধান করার সুস্পষ্ট উপায় হ'ল .catchঅভ্যন্তরীণ প্রতিশ্রুতিগুলি সহজভাবে কল করা এবং তাদের কলব্যাক থেকে ত্রুটি ফিরিয়ে দেওয়া।

let a = new Promise((res, rej) => res('Resolved!')),
    b = new Promise((res, rej) => rej('Rejected!')),
    c = a.catch(e => { console.log('"a" failed.'); return e; }),
    d = b.catch(e => { console.log('"b" failed.'); return e; });

Promise.all([c, d])
  .then(result => console.log('Then', result)) // Then ["Resolved!", "Rejected!"]
  .catch(err => console.log('Catch', err));

Promise.all([a.catch(e => e), b.catch(e => e)])
  .then(result => console.log('Then', result)) // Then ["Resolved!", "Rejected!"]
  .catch(err => console.log('Catch', err));

এটি আরও একধাপ এগিয়ে নিয়ে যাওয়া, আপনি জেনেরিক ধরা হ্যান্ডলারটি দেখতে দেখতে দেখতে এটি লিখতে পারেন:

const catchHandler = error => ({ payload: error, resolved: false });

তাহলে আপনি করতে পারেন

> Promise.all([a, b].map(promise => promise.catch(catchHandler))
    .then(results => console.log(results))
    .catch(() => console.log('Promise.all failed'))
< [ 'Resolved!',  { payload: Promise, resolved: false } ]

এটির সাথে সমস্যাটি হ'ল ধরা পড়া মানগুলির নন-ক্যাচড মানগুলির চেয়ে আলাদা ইন্টারফেস থাকবে, তাই এটি পরিষ্কার করার জন্য আপনি এমন কিছু করতে পারেন:

const successHandler = result => ({ payload: result, resolved: true });

সুতরাং এখন আপনি এটি করতে পারেন:

> Promise.all([a, b].map(result => result.then(successHandler).catch(catchHandler))
    .then(results => console.log(results.filter(result => result.resolved))
    .catch(() => console.log('Promise.all failed'))
< [ 'Resolved!' ]

তারপরে এটি শুকনো রাখতে, আপনি বেঞ্জামিনের উত্তর পেতে পারেন:

const reflect = promise => promise
  .then(successHandler)
  .catch(catchHander)

এখন এটি দেখতে কেমন দেখাচ্ছে

> Promise.all([a, b].map(result => result.then(successHandler).catch(catchHandler))
    .then(results => console.log(results.filter(result => result.resolved))
    .catch(() => console.log('Promise.all failed'))
< [ 'Resolved!' ]

দ্বিতীয় সমাধানের সুবিধাগুলি হ'ল এটি বিমূর্ত এবং DRY। খারাপ দিকটি হ'ল আপনার আরও কোড রয়েছে এবং জিনিসগুলিকে সামঞ্জস্যপূর্ণ করার জন্য আপনার সমস্ত প্রতিশ্রুতি প্রতিফলিত করতে হবে you

আমি আমার সমাধানটিকে স্পষ্ট এবং কেআইএসএস হিসাবে চিহ্নিত করব তবে সত্যই কম শক্ত। ইন্টারফেস গ্যারান্টি দেয় না যে আপনি প্রতিশ্রুতিটি সফল হয়েছে কিনা তা ব্যর্থ হয়েছে কিনা তা আপনি ঠিক জানেন।

উদাহরণস্বরূপ আপনার এটি থাকতে পারে:

const a = Promise.resolve(new Error('Not beaking, just bad'));
const b = Promise.reject(new Error('This actually didnt work'));

এটি ধরা পড়বে না a.catch, তাই

> Promise.all([a, b].map(promise => promise.catch(e => e))
    .then(results => console.log(results))
< [ Error, Error ]

কোনটি মারাত্মক এবং কোনটি ছিল তা বলার উপায় নেই। যদি তা গুরুত্বপূর্ণ হয় তবে আপনি প্রয়োগ করতে চান এবং এটি ইন্টারফেস করতে চান যা সফল হয়েছে কিনা (যা reflectকরে) তা ট্র্যাক করে।

আপনি যদি কেবল ত্রুটিগুলি নিখুঁতভাবে পরিচালনা করতে চান, তবে আপনি কেবল ত্রুটিগুলি অনির্ধারিত মান হিসাবে বিবেচনা করতে পারেন:

> Promise.all([a.catch(() => undefined), b.catch(() => undefined)])
    .then((results) => console.log('Known values: ', results.filter(x => typeof x !== 'undefined')))
< [ 'Resolved!' ]

আমার ক্ষেত্রে, ত্রুটিটি বা এটি কীভাবে ব্যর্থ হয়েছিল তা আমার জানা দরকার না - আমার মূল্য আছে কি না তা কেবল যত্নশীল। প্রতিশ্রুতি উত্পন্ন ফাংশনটি নির্দিষ্ট ত্রুটি লগ করার বিষয়ে উদ্বিগ্ন হতে দেব।

const apiMethod = () => fetch()
  .catch(error => {
    console.log(error.message);
    throw error;
  });

এইভাবে, বাকি অ্যাপ্লিকেশনগুলি যদি এটি চায় তবে এটির ত্রুটিটিকে উপেক্ষা করতে পারে এবং এটি চাইলে এটিকে অপরিজ্ঞাত মান হিসাবে গণ্য করতে পারে।

আমি চাই যে আমার উচ্চ স্তরের ফাংশনগুলি নিরাপদে ব্যর্থ হয় এবং এর নির্ভরতা কেন ব্যর্থ হয় তার বিশদ সম্পর্কে চিন্তা না করে এবং আমি যখন ট্রেড অফ করতে হয় তখন আমি ডিআইওয়াইয়ের চেয়েও কেআইএসএসকেই বেশি পছন্দ করি - যা শেষ পর্যন্ত আমি ব্যবহার না করা বেছে নিয়েছিলাম reflect


1
@ বেনজামিন আমি মনে করি @ নাথানের সমাধান খুব সহজবোধ্য এবং মূর্তিযুক্ত Promises আপনার reflectউন্নত কোড পুনরায় ব্যবহারের সময় এটি বিমূর্ততার আরও একটি স্তরও প্রতিষ্ঠিত করে। যেহেতু নাথনের উত্তর এখনও পর্যন্ত আপনার তুলনায় কেবলমাত্র কিছু অংশের আপত্তি পেয়েছে, তাই আমি অবাক হয়েছি যে এটি তার সমাধানের সাথে কোনও সমস্যার ইঙ্গিত কিনা, যা আমি এখনও স্বীকৃতি দিতে পারি নি।

2
@ LUH3417 এই সমাধানটি ধারণাগতভাবে কম শব্দ কারণ এটি ত্রুটিগুলিকে মান হিসাবে বিবেচনা করে এবং ত্রুটিগুলি অ-ত্রুটিগুলি থেকে পৃথক করে না। উদাহরণস্বরূপ, যদি প্রতিশ্রুতিগুলির কোনও একটি নিক্ষিপ্ত হতে পারে এমন একটি মানকে বৈধভাবে সমাধান করে (যা সম্পূর্ণভাবে সম্ভব) এটি খুব খারাপভাবে ভেঙে যায়।
বেনিয়ামিন গ্রুইনবাউম 2:25

2
@ বেনজামিন গ্রুয়েনবাউম উদাহরণস্বরূপ, এর new Promise((res, rej) => res(new Error('Legitimate error'))থেকে পৃথক হবে না new Promise(((res, rej) => rej(new Error('Illegitimate error'))? বা আরও, আপনি দ্বারা ফিল্টার করতে সক্ষম হবে না x.status? আমি এই উত্তরটি আমার উত্তরে যুক্ত করব যাতে পার্থক্য আরও স্পষ্ট হয়
নাথান হাগেন

3
এটি একটি দুর্বল ধারণা হওয়ার কারণ হ'ল এটি প্রতিশ্রুতি বাস্তবায়নের জন্য নির্দিষ্ট ব্যবহারের ক্ষেত্রে কেবলমাত্র কোনও নির্দিষ্ট Promise.all()প্রকারের ক্ষেত্রে ব্যবহৃত হয় , এটি তখন প্রতিজ্ঞাত গ্রাহকের কাছেও জানতে বাধ্য হয় যে একটি নির্দিষ্ট প্রতিশ্রুতি প্রত্যাখাত হবে না তবে হবে এটি ত্রুটি গ্রাস। আসলে reflect()পদ্ধতিটি কম 'বিমূর্ত' এবং এটি কল করে আরও স্পষ্ট করা যায় PromiseEvery(promises).then(...)
নিল

33

সেখানে একটি ভ্যানিলা জাভাস্ক্রিপ্টে Promise.allSettled, যা এই স্থানীয়ভাবে সম্পন্ন করতে পারে এমন কোনও ফাংশনের জন্য সমাপ্ত প্রস্তাব রয়েছে : যা এটিকে চতুর্থ পর্যায়ে পরিণত করেছে, ES2020 এ অফিসিয়াল করা হয়েছে এবং এটি সমস্ত আধুনিক পরিবেশে প্রয়োগ করা হয়েছে । এটি অন্য উত্তরটিতেreflect ফাংশনের সাথে খুব মিল । প্রস্তাবের পৃষ্ঠা থেকে এখানে একটি উদাহরণ দেওয়া আছে। আগে, আপনাকে করতে হবে:

function reflect(promise) {
  return promise.then(
    (v) => {
      return { status: 'fulfilled', value: v };
    },
    (error) => {
      return { status: 'rejected', reason: error };
    }
  );
}

const promises = [ fetch('index.html'), fetch('https://does-not-exist/') ];
const results = await Promise.all(promises.map(reflect));
const successfulPromises = results.filter(p => p.status === 'fulfilled');

Promise.allSettledপরিবর্তে ব্যবহার করে উপরেরটি সমান হবে:

const promises = [ fetch('index.html'), fetch('https://does-not-exist/') ];
const results = await Promise.allSettled(promises);
const successfulPromises = results.filter(p => p.status === 'fulfilled');

আধুনিক পরিবেশ যারা ব্যবহার করেন তারা এই পদ্ধতিটি ব্যবহার করতে সক্ষম হবেন কোনও লাইব্রেরি ছাড়াই । এর মধ্যে নিম্নলিখিত স্নিপেটটি সমস্যা ছাড়াই চালানো উচিত:

Promise.allSettled([
  Promise.resolve('a'),
  Promise.reject('b')
])
  .then(console.log);

আউটপুট:

[
  {
    "status": "fulfilled",
    "value": "a"
  },
  {
    "status": "rejected",
    "reason": "b"
  }
]

পুরানো ব্রাউজারগুলির জন্য, এখানে একটি স্পেস-কমপ্লায়েন্ট পলফিল রয়েছে


1
এটি পর্যায়ে 4 এবং ES2020 এ অবতরণ করার কথা।
এস্তাস ফ্লাস্ক

নোড 12 এও পাওয়া যায় :)
কলম্ব এম

অন্য উত্তরগুলি এখনও বৈধ থাকলেও এটি এই সমস্যাটি সমাধানের সর্বাধিক বর্তমান উপায় হিসাবে এটি আরও বেশি হওয়া উচিত।
জ্যাকব

9

আমি সত্যিই বেনজামিনের উত্তর পছন্দ করি এবং তিনি কীভাবে সমস্ত প্রতিশ্রুতি সর্বদা সমাধানযোগ্য-তবে-কখনও-ত্রুটি-তত-ফল-এর ফলাফল হিসাবে পরিণত করেন। :)
আপনি বিকল্পগুলির সন্ধান করছেন এমন ক্ষেত্রে আপনার অনুরোধটি সম্পর্কে এখানে আমার প্রচেষ্টা। এই পদ্ধতিটি কেবল ত্রুটিগুলিকে বৈধ ফলাফল হিসাবে বিবেচনা করে এবং Promise.allঅন্যথায় এর মতো কোড করা হয়:

Promise.settle = function(promises) {
  var results = [];
  var done = promises.length;

  return new Promise(function(resolve) {
    function tryResolve(i, v) {
      results[i] = v;
      done = done - 1;
      if (done == 0)
        resolve(results);
    }

    for (var i=0; i<promises.length; i++)
      promises[i].then(tryResolve.bind(null, i), tryResolve.bind(null, i));
    if (done == 0)
      resolve(results);
  });
}

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

2
ঠিক আছে, নিষ্পত্তি সত্যই একটি ভাল নাম হবে। :)
কুবা ওয়াইরোস্টেক

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

আপনি কি দয়া করে Promiseকনস্ট্রাক্টরটিকে সঠিকভাবে ব্যবহার করতে পারেন (এবং সেই var resolveজিনিসটি এড়ানো )?
বার্গি

বার্গি, আপনি প্রয়োজনীয় বিবেচনা করলেও উত্তরটি নির্দ্বিধায় ফেলুন।
কুবা ওয়াইরোস্টেক

5
var err;
Promise.all([
    promiseOne().catch(function(error) { err = error;}),
    promiseTwo().catch(function(error) { err = error;})
]).then(function() {
    if (err) {
        throw err;
    }
});

এটি Promise.allকোনও প্রত্যাখ্যাত প্রতিশ্রুতি গ্রাস করবে এবং ত্রুটিটি একটি ভেরিয়েবেলে সংরক্ষণ করবে, সুতরাং যখন প্রতিশ্রুতিগুলির সমস্ত সমাধান হয়ে যায় তখন তা ফিরে আসবে। তারপরে আপনি ত্রুটিটি আবার ফেলে দিতে পারেন বা যা কিছু করতে পারেন। এইভাবে, আমি অনুমান করি আপনি প্রথমটির পরিবর্তে শেষ প্রত্যাখ্যানটি পেয়ে যাবেন।


1
দেখে মনে হচ্ছে এটিকে একটি অ্যারে তৈরি করে এবং ব্যবহার করে err.push(error)ত্রুটিগুলি একত্রিত করতে পারে, সুতরাং সমস্ত ত্রুটি বুদ্বুদ করা যেতে পারে।
পিএস

4

আমার একই সমস্যা ছিল এবং এটি নিম্নলিখিত উপায়ে সমাধান করেছি:

const fetch = (url) => {
  return node-fetch(url)
    .then(result => result.json())
    .catch((e) => {
      return new Promise((resolve) => setTimeout(() => resolve(fetch(url)), timeout));
    });
};

tasks = [fetch(url1), fetch(url2) ....];

Promise.all(tasks).then(......)

যে ক্ষেত্রে Promise.allজন্য প্রতি প্রতিশ্রুতি আসবে অপেক্ষা করবে resolvedবা rejectedরাষ্ট্র।

এবং এই সমাধানটি পেয়ে আমরা catchএকটি অবরুদ্ধ উপায়ে "কার্যকর করা বন্ধ করছি" । প্রকৃতপক্ষে, আমরা কোনও কিছু থামছি না, আমরা কেবল Promiseএকটি মুলতুবি অবস্থায় ফিরে আসছি যা Promiseসময়সীমা শেষ হওয়ার পরে সমাধান হওয়ার পরে অন্যটিকে ফিরিয়ে দেয়।


আপনি যখন দৌড়াবেন তবে তা ইচ্ছামত সমস্ত প্রতিশ্রুতি দেয় Promise.all। আমি যখন সমস্ত প্রতিশ্রুতি দেওয়া হয় তখন তা শোনার উপায় খুঁজছি, তবে সেগুলি নিজেই প্রার্থনা করব না। ধন্যবাদ।
সুডোপ্লাজ

@ সুডোপ্লাজ পদ্ধতিটি এটি all()করে যে, এটি সমস্ত প্রতিশ্রুতি পূর্ণ হওয়ার অপেক্ষায় রয়েছে বা এর কমপক্ষে একটি প্রত্যাখ্যান করে।
ব্যবহারকারী 1016265

এটি সত্য, তবে এটি কেবল অপেক্ষা করে না, এটি প্রকৃতপক্ষে প্রক্রিয়াটি শুরু করে / শুরু করে। আপনি যদি প্রতিশ্রুতি দিয়েছিলেন যে কোথাও কোথাও এটি সম্ভব হয় না, তবে বেকেস .allসমস্ত কিছু আপ করে দেয়।
সুডোপ্লাজ

@ সুডোপ্লিজ আশা করছেন এটি আপনার মতামত পরিবর্তন করবে jsfiddle.net/d1z1vey5
ব্যবহারকারী 1016265

3
আমি সংশোধন করেছি. এখন অবধি আমি ভেবেছিলাম প্রতিশ্রুতি কেবল তখনই চালিত হয় যখন কেউ তাদের ডাকে (ওরফে এ thenবা একটি .allকল) তবে তারা তৈরি হওয়ার পরে চালায়।
সুডোপ্লাজ

2

এটি কীভাবে এটি করে তার সাথে সামঞ্জস্য হওয়া উচিত :

if(!Promise.allSettled) {
    Promise.allSettled = function (promises) {
        return Promise.all(promises.map(p => Promise.resolve(p).then(v => ({
            state: 'fulfilled',
            value: v,
        }), r => ({
            state: 'rejected',
            reason: r,
        }))));
    };
}

2

বেঞ্জামিন গ্রুইনবাউমের উত্তর অবশ্যই দুর্দান্ত ,. তবে আমি এটিও দেখতে পারি যে নাথান হ্যাগেনের দৃষ্টিভঙ্গিটি অ্যাবস্ট্রাকশন স্তরের সাথে অস্পষ্ট বলে মনে হয়েছিল। সংক্ষিপ্ত বস্তুর বৈশিষ্ট্য থাকার মতোe & v তেমন সহায়তা করে না তবে অবশ্যই এটি পরিবর্তন করা যেতে পারে।

জাভাস্ক্রিপ্টে স্ট্যান্ডার্ড ত্রুটি অবজেক্ট রয়েছে, বলা হয় Error। আদর্শভাবে আপনি সর্বদা এটির উদাহরণ / বংশধর নিক্ষেপ করেন। সুবিধাটি হ'ল আপনি করতে পারেনinstanceof Error এবং আপনি জানেন যে কোনও কিছু ত্রুটি।

সুতরাং এই ধারণাটি ব্যবহার করে, আমি এখানে সমস্যাটি গ্রহণ করব।

মূলত ত্রুটিটি ধরুন, যদি ত্রুটিটি ত্রুটি প্রকারের না হয় তবে ত্রুটিটি কোনও ত্রুটিযুক্ত বস্তুর অভ্যন্তরে মোড়ানো। ফলস্বরূপ অ্যারেতে হয় সমাধান করা মান, বা ত্রুটিযুক্ত বস্তু যা আপনি চেক করতে পারেন।

ক্যাচের অভ্যন্তরের উদাহরণটি যদি আপনি কিছু বাহ্যিক গ্রন্থাগার ব্যবহার করেন যা সম্ভবত এটির reject("error")পরিবর্তে করা হয়েছিল reject(new Error("error"))

অবশ্যই আপনি প্রতিশ্রুতি রাখতে পারতেন যদি আপনি কোনও ত্রুটি সমাধান করেন তবে এটি সম্ভবত সম্ভবত উদাহরণ হিসাবে দেখা যায়, তবুও কোনও ত্রুটি হিসাবে বিবেচিত হবে sense

এটি করার আরেকটি সুবিধা, অ্যারে ধ্বংস করা সহজ রাখা হয়েছে।

const [value1, value2] = PromiseAllCatch(promises);
if (!(value1 instanceof Error)) console.log(value1);

পরিবর্তে

const [{v: value1, e: error1}, {v: value2, e: error2}] = Promise.all(reflect..
if (!error1) { console.log(value1); }

আপনি তর্ক করতে পারেন যে !error1চেকটি উদাহরণের চেয়ে সহজ, তবে আপনার উভয়টিকেই ধ্বংস করতে হবে v & e

function PromiseAllCatch(promises) {
  return Promise.all(promises.map(async m => {
    try {
      return await m;
    } catch(e) {
      if (e instanceof Error) return e;
      return new Error(e);
    }
  }));
}


async function test() {
  const ret = await PromiseAllCatch([
    (async () => "this is fine")(),
    (async () => {throw new Error("oops")})(),
    (async () => "this is ok")(),
    (async () => {throw "Still an error";})(),
    (async () => new Error("resolved Error"))(),
  ]);
  console.log(ret);
  console.log(ret.map(r =>
    r instanceof Error ? "error" : "ok"
    ).join(" : ")); 
}

test();


2

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

const promise = arg => {
  return new Promise((resolve, reject) => {
      setTimeout(() => {
        try{
          if(arg != 2)
            return resolve({success: true, data: arg});
          else
            throw new Error(arg)
        }catch(e){
          return resolve({success: false, error: e, data: arg})
        }
      }, 1000);
  })
}

Promise.all([1,2,3,4,5].map(e => promise(e))).then(d => console.log(d))


1
এটি চারপাশে একটি দুর্দান্ত কাজ দেখায়, মার্জিত নয় তবে কাজ করবে
সানি টাম্বি

1

আমি নিম্নলিখিত অফার সামান্য ভিন্ন পদ্ধতি মনে করি ... তুলনা fn_fast_fail()সঙ্গে fn_slow_fail()... যদিও আধুনিক যেমন ব্যর্থ না ... আপনি এক বা উভয় যদি পরীক্ষা করতে পারবেন aএবং bএকটি দৃষ্টান্ত হল Errorএবং throwযে Errorআপনি পৌঁছাতে এটি করতে চান যদি catchব্লক (যেমন if (b instanceof Error) { throw b; })। Jsfiddle দেখুন ।

var p1 = new Promise((resolve, reject) => { 
    setTimeout(() => resolve('p1_delayed_resolvement'), 2000); 
}); 

var p2 = new Promise((resolve, reject) => {
    reject(new Error('p2_immediate_rejection'));
});

var fn_fast_fail = async function () {
    try {
        var [a, b] = await Promise.all([p1, p2]);
        console.log(a); // "p1_delayed_resolvement"
        console.log(b); // "Error: p2_immediate_rejection"
    } catch (err) {
        console.log('ERROR:', err);
    }
}

var fn_slow_fail = async function () {
    try {
        var [a, b] = await Promise.all([
            p1.catch(error => { return error }),
            p2.catch(error => { return error })
        ]);
        console.log(a); // "p1_delayed_resolvement"
        console.log(b); // "Error: p2_immediate_rejection"
    } catch (err) {
        // we don't reach here unless you throw the error from the `try` block
        console.log('ERROR:', err);
    }
}

fn_fast_fail(); // fails immediately
fn_slow_fail(); // waits for delayed promise to resolve

0

এখানে আমার রীতি আছে settledPromiseAll()

const settledPromiseAll = function(promisesArray) {
  var savedError;

  const saveFirstError = function(error) {
    if (!savedError) savedError = error;
  };
  const handleErrors = function(value) {
    return Promise.resolve(value).catch(saveFirstError);
  };
  const allSettled = Promise.all(promisesArray.map(handleErrors));

  return allSettled.then(function(resolvedPromises) {
    if (savedError) throw savedError;
    return resolvedPromises;
  });
};

তুলনা করা Promise.all

  • যদি সমস্ত প্রতিশ্রুতিগুলি সমাধান হয় তবে এটি মানক হিসাবে ঠিক সম্পাদন করে।

  • যদি আরও একটি প্রতিশ্রুতি প্রত্যাখাত হয় তবে এটি প্রথমটি মানক হিসাবে অনেকটা প্রত্যাখ্যান করে তবে এটি সমস্ত প্রতিশ্রুতি সমাধান / প্রত্যাখ্যানের অপেক্ষা করে।

সাহসীদের জন্য আমরা পরিবর্তন করতে পারি Promise.all():

(function() {
  var stdAll = Promise.all;

  Promise.all = function(values, wait) {
    if(!wait)
      return stdAll.call(Promise, values);

    return settledPromiseAll(values);
  }
})();

সাবধান । সাধারণভাবে আমরা কখনই বিল্ট-ইনগুলি পরিবর্তন করি না, কারণ এটি অন্যান্য সম্পর্কযুক্ত জেএস গ্রন্থাগারগুলিকে ভেঙে দিতে পারে বা ভবিষ্যতে জেএস মানদণ্ডে পরিবর্তনগুলির সাথে সংঘর্ষে লিপ্ত হতে পারে।

আমার settledPromiseallসাথে পিছনে সামঞ্জস্যপূর্ণPromise.all এবং এর কার্যকারিতা প্রসারিত করে।

লোকেরা যারা মান বিকাশ করছে - কেন এটি একটি নতুন প্রতিজ্ঞার মান হিসাবে অন্তর্ভুক্ত করবেন না?


0

Promise.allআধুনিক async/awaitপদ্ধতি ব্যবহার করে

const promise1 = //...
const promise2 = //...

const data = await Promise.all([promise1, promise2])

const dataFromPromise1 = data[0]
const dataFromPromise2 = data[1]

-1

আমি করবো:

var err = [fetch('index.html').then((success) => { return Promise.resolve(success); }).catch((e) => { return Promise.resolve(e); }),
fetch('http://does-not-exist').then((success) => { return Promise.resolve(success); }).catch((e) => { return Promise.resolve(e); })];

Promise.all(err)
.then(function (res) { console.log('success', res) })
.catch(function (err) { console.log('error', err) }) //never executed

-1

আপনি আপনার যুক্তি সিঙ্ক্রোনাস এক্সিকিউটার nsynjs এর মাধ্যমে ধারাবাহিকভাবে সম্পাদন করতে পারেন । এটি প্রতিটি প্রতিশ্রুতিতে বিরতি দেবে, রেজোলিউশন / প্রত্যাখ্যানের জন্য অপেক্ষা করবে, এবং হয় dataসম্পত্তিতে সমাধানের ফলাফল অর্পণ করবে , বা একটি ব্যতিক্রম নিক্ষেপ করবে (পরিচালনা করার জন্য যা আপনার চেষ্টা করতে হবে / ব্লক ব্লক লাগবে)। এখানে একটি উদাহরণ:

function synchronousCode() {
    function myFetch(url) {
        try {
            return window.fetch(url).data;
        }
        catch (e) {
            return {status: 'failed:'+e};
        };
    };
    var arr=[
        myFetch("https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"),
        myFetch("https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/NONEXISTANT.js"),
        myFetch("https://ajax.NONEXISTANT123.com/ajax/libs/jquery/2.0.0/NONEXISTANT.js")
    ];
    
    console.log('array is ready:',arr[0].status,arr[1].status,arr[2].status);
};

nsynjs.run(synchronousCode,{},function(){
    console.log('done');
});
<script src="https://rawgit.com/amaksr/nsynjs/master/nsynjs.js"></script>


-1

আমি ES5 সাল থেকে নিম্নলিখিত কোডগুলি ব্যবহার করছি।

Promise.wait = function(promiseQueue){
    if( !Array.isArray(promiseQueue) ){
        return Promise.reject('Given parameter is not an array!');
    }

    if( promiseQueue.length === 0 ){
        return Promise.resolve([]);
    }

    return new Promise((resolve, reject) =>{
        let _pQueue=[], _rQueue=[], _readyCount=false;
        promiseQueue.forEach((_promise, idx) =>{
            // Create a status info object
            _rQueue.push({rejected:false, seq:idx, result:null});
            _pQueue.push(Promise.resolve(_promise));
        });

        _pQueue.forEach((_promise, idx)=>{
            let item = _rQueue[idx];
            _promise.then(
                (result)=>{
                    item.resolved = true;
                    item.result = result;
                },
                (error)=>{
                    item.resolved = false;
                    item.result = error;
                }
            ).then(()=>{
                _readyCount++;

                if ( _rQueue.length === _readyCount ) {
                    let result = true;
                    _rQueue.forEach((item)=>{result=result&&item.resolved;});
                    (result?resolve:reject)(_rQueue);
                }
            });
        });
    });
};

ব্যবহারের স্বাক্ষরটি ঠিক এর মতো Promise.all। প্রধান পার্থক্য হ'ল Promise.waitতাদের কাজ শেষ করার জন্য সমস্ত প্রতিশ্রুতির জন্য অপেক্ষা করবে।


-1

আমি জানি যে এই প্রশ্নের অনেক উত্তর রয়েছে এবং আমি অবশ্যই নিশ্চিত (অবশ্যই সব না থাকলে) সঠিক। তবে এই উত্তরগুলির যুক্তি / প্রবাহ বুঝতে আমার পক্ষে খুব কষ্ট হয়েছিল।

সুতরাং আমি অরিজিনাল বাস্তবায়নটির দিকে নজর রেখেছিলাম এবং কোনও Promise.all()যুক্তি ব্যর্থ হলে কার্যকর করা বন্ধ না করে ব্যতীত আমি সেই যুক্তিটি অনুকরণ করার চেষ্টা করেছি।

  public promiseExecuteAll(promisesList: Promise<any>[] = []): Promise<{ data: any, isSuccess: boolean }[]>
  {
    let promise: Promise<{ data: any, isSuccess: boolean }[]>;

    if (promisesList.length)
    {
      const result: { data: any, isSuccess: boolean }[] = [];
      let count: number = 0;

      promise = new Promise<{ data: any, isSuccess: boolean }[]>((resolve, reject) =>
      {
        promisesList.forEach((currentPromise: Promise<any>, index: number) =>
        {
          currentPromise.then(
            (data) => // Success
            {
              result[index] = { data, isSuccess: true };
              if (promisesList.length <= ++count) { resolve(result); }
            },
            (data) => // Error
            {
              result[index] = { data, isSuccess: false };
              if (promisesList.length <= ++count) { resolve(result); }
            });
        });
      });
    }
    else
    {
      promise = Promise.resolve([]);
    }

    return promise;
  }

ব্যাখ্যা:
- ইনপুটটি লুপ করুন promisesListএবং প্রতিটি প্রতিশ্রুতি কার্যকর করুন ।
- প্রতিশ্রুতিটি সমাধান হয়েছে বা প্রত্যাখ্যানযোগ্য তা বিবেচনাধীন নয়: প্রতিশ্রুতিটির ফলাফল resultঅনুযায়ী একটি অ্যারেতে সংরক্ষণ করুন index। সমাধান / প্রত্যাখ্যান স্থিতি ( isSuccess) কেও সংরক্ষণ করুন ।
- সমস্ত প্রতিশ্রুতি শেষ হয়ে গেলে, অন্য সকলের ফলাফলের সাথে একটি প্রতিশ্রুতি ফিরিয়ে দিন।

ব্যবহারের উদাহরণ:

const p1 = Promise.resolve("OK");
const p2 = Promise.reject(new Error(":-("));
const p3 = Promise.resolve(1000);

promiseExecuteAll([p1, p2, p3]).then((data) => {
  data.forEach(value => console.log(`${ value.isSuccess ? 'Resolve' : 'Reject' } >> ${ value.data }`));
});

/* Output: 
Resolve >> OK
Reject >> :-(
Resolve >> 1000
*/

2
পুনরায় বাস্তবায়নের চেষ্টা করবেন না Promise.allনিজেকে , এমন অনেকগুলি জিনিস রয়েছে যা ভুল হয়ে যাবে। উদাহরণস্বরূপ আপনার সংস্করণ খালি ইনপুটগুলি পরিচালনা করে না।
বার্গি

-4

আপনি কোন প্রতিশ্রুতি গ্রন্থাগারটি ব্যবহার করছেন তা আমি জানি না, তবে বেশিরভাগের কাছে অ্যালসেট্টেলের মতো কিছু রয়েছে

সম্পাদনা: ঠিক আছে আপনি যেহেতু বাহ্যিক লাইব্রেরি ছাড়া প্লেইন ES6 ব্যবহার করতে চান, তেমন কোনও পদ্ধতি নেই।

অন্য কথায়: আপনাকে নিজের প্রতিশ্রুতিগুলি নিজে হাতে নিতে হবে এবং সমস্ত প্রতিশ্রুতি নিষ্পত্তি হওয়ার সাথে সাথে একটি নতুন সম্মিলিত প্রতিশ্রুতি সমাধান করতে হবে।


আমি আমার প্রশ্নটি স্পষ্ট করতে সম্পাদনা করেছি - যেহেতু ES6 প্রতিশ্রুতি নিয়ে আসে, তাই আমি যেটিকে প্রাথমিক কার্যকারিতা বলে মনে করব তার জন্য অন্য একটি গ্রন্থাগার ব্যবহার করা এড়াতে চাই। আমি অনুমান করেছি যে উত্তরটি পাওয়ার ভাল জায়গাটি হ'ল প্রতিশ্রুতি পাঠাগারগুলির মধ্য থেকে উত্সটি অনুলিপি করা।
নাথান হাগেন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.