Promise.all: सुलझे हुए मूल्यों का क्रम


188

MDN को देखते हुए ऐसा लगता है कि वादे valuesके then()कॉलबैक को पारित कर दिया गया है । वादों के क्रम में मूल्य शामिल हैं। उदाहरण के लिए:

var somePromises = [1, 2, 3, 4, 5].map(Promise.resolve);
return Promise.all(somePromises).then(function(results) {
  console.log(results) //  is [1, 2, 3, 4, 5] the guaranteed result?
});

क्या कोई युक्ति बता सकता है कि किस क्रम में valuesहोना चाहिए?

PS: रनिंग कोड जैसा दिखाया गया है कि यह सच प्रतीत होता है, हालांकि यह निश्चित रूप से कोई सबूत नहीं है - यह संयोग हो सकता है।

जवाबों:


271

शीघ्र ही, आदेश संरक्षित है

आपके द्वारा लिंक किए गए चश्मे के बाद, एक पैरामीटर के रूप में एक (जो एक ऐसी वस्तु है जो इंटरफ़ेस का समर्थन करता है) Promise.all(iterable)लेता iterableहै, Iteratorऔर बाद में PerformPromiseAll( iterator, constructor, resultCapability)इसके साथ कॉल करता है, जहां बाद वाले लूप iterableका उपयोग करते हैं IteratorStep(iterator)
इसका मतलब यह है कि यदि यदि आप जिस चलने योग्य से गुजरते हैं, Promise.all()उस पर सख्ती से आदेश दिया गया है, तो वे अभी भी एक बार पारित होने का आदेश देंगे।

Promise.all() Resolveजहां प्रत्येक हल किए गए वादे में आंतरिक [[Index]]स्लॉट होता है, के माध्यम से हल किया जाता है , जो मूल इनपुट में वादे के सूचकांक को चिह्नित करता है।


इसका मतलब यह है कि आउटपुट सख्ती से इनपुट के रूप में तब तक ऑर्डर किया जाता है जब तक इनपुट सख्ती से ऑर्डर किया जाता है (उदाहरण के लिए, एक सरणी)।

आप इसे नीचे दिए गए फ़ेडल (ES6) में देख सकते हैं:

// Used to display results
const write = msg => {
  document.body.appendChild(document.createElement('div')).innerHTML = msg;
};

// Different speed async operations
const slow = new Promise(resolve => {
  setTimeout(resolve, 200, 'slow');
});
const instant = 'instant';
const quick = new Promise(resolve => {
  setTimeout(resolve, 50, 'quick');
});

// The order is preserved regardless of what resolved first
Promise.all([slow, instant, quick]).then(responses => {
  responses.map(response => write(response));
});


1
कैसे एक चलने योग्य सख्ती से आदेश नहीं दिया जाएगा? कोई भी चलने योग्य "कड़ाई से आदेश दिया जाता है" इस आदेश से यह अपने मूल्यों को पैदा करता है।
बेंजामिन ग्रुएनबाम

नोट - फ़ायरफ़ॉक्स एकमात्र ब्राउज़र है जो वादों में पुनरावृत्तियों को सही ढंग से लागू कर रहा है। throwयदि आप इससे चलने वाले से गुजरते हैं तो क्रोम वर्तमान में एक एक्सेप्टेंस होगा Promise.all। इसके अलावा, मैं किसी भी उपयोगकर्ता-वादे के क्रियान्वयन के बारे में नहीं जानता हूँ जो वर्तमान में चलने वाले पुनरावृत्तियों का समर्थन करता है, हालांकि कई ने इस पर बहस की है और उस समय इसके खिलाफ निर्णय लिया है।
बेंजामिन ग्रुएनबाम

3
@BenjaminGruenbaum क्या पुनरावृत्त होना संभव नहीं है जो दो बार पुनरावृत्त होने पर दो अलग-अलग ऑर्डर तैयार करता है? उदाहरण के लिए, कार्ड का एक डेक जो अनियमित क्रम में कार्ड का उत्पादन करता है जब इसे पुनरावृत्त किया जाता है? मुझे नहीं पता कि "कड़ाई से आदेश दिया गया" यहां सही शब्दावली है, लेकिन सभी पुनरावृत्तियों में एक निश्चित क्रम नहीं है। तो मुझे लगता है यह कहना है कि उचित है iterators "सख्ती से आदेश दिया" कर रहे हैं (यह सोचते हैं कि सही शब्द है), लेकिन iterables नहीं हैं।
JLRishe

3
@JLRishe मुझे लगता है कि आप सही हैं, यह वास्तव में पुनरावृत्तियां हैं जिन्हें आदेश दिया गया है - पुनरावृत्तियां नहीं हैं।
बेंजामिन Gruenbaum

8
यह ध्यान देने योग्य है कि वादे चेन नहीं करते हैं। जब आप उसी क्रम में रिज़ॉल्यूशन प्राप्त करेंगे, तो वादों पर कार्रवाई किए जाने के बारे में कोई गारंटी नहीं है। दूसरे शब्दों Promise.allमें, एक के बाद एक वादों की एक सरणी चलाने के लिए इस्तेमाल नहीं किया जा सकता है। इटरेटर में लोड किए गए वादों को अनुमानित रूप से काम करने के लिए एक दूसरे से स्वतंत्र होने की आवश्यकता है।
एंड्रयू एडी

49

जैसा कि पिछले उत्तर पहले ही बता चुके हैं, Promise.allमूल वादों के इनपुट क्रम के अनुरूप एक सरणी के साथ सभी हल किए गए मानों को एकत्र करता है (देखें एग्रीगेटिंग प्रॉमिस देखें )।

हालाँकि, मैं यह बताना चाहूंगा कि ऑर्डर केवल क्लाइंट की तरफ संरक्षित है!

डेवलपर को ऐसा लगता है कि वादे क्रम में पूरे हुए थे लेकिन वास्तव में, वादे अलग गति से संसाधित किए जाते हैं। यह जानना महत्वपूर्ण है कि जब आप एक दूरस्थ बैकएंड के साथ काम करते हैं क्योंकि बैकएंड को एक अलग क्रम में आपके वादे प्राप्त हो सकते हैं।

यहाँ एक उदाहरण है जो टाइमआउट का उपयोग करके समस्या को प्रदर्शित करता है:

Promise.all

const myPromises = [
  new Promise((resolve) => setTimeout(() => {resolve('A (slow)'); console.log('A (slow)')}, 1000)),
  new Promise((resolve) => setTimeout(() => {resolve('B (slower)'); console.log('B (slower)')}, 2000)),
  new Promise((resolve) => setTimeout(() => {resolve('C (fast)'); console.log('C (fast)')}, 10))
];

Promise.all(myPromises).then(console.log)

ऊपर दिखाए गए कोड में, तीन वादे (ए, बी, सी) दिए गए हैं Promise.all। तीन वादे अलग-अलग गति से निष्पादित होते हैं (C सबसे तेज़ और B सबसे धीमा है)। इसीलिए console.logइस क्रम में वादों के विवरण दिखाए गए हैं:

C (fast) 
A (slow)
B (slower)

यदि वादे AJAX कॉल हैं, तो एक दूरस्थ बैकएंड इस क्रम में इन मूल्यों को प्राप्त करेगा। लेकिन क्लाइंट पक्ष Promise.allयह सुनिश्चित करता है कि परिणाम myPromisesसरणी के मूल पदों के अनुसार क्रमबद्ध हों । इसलिए अंतिम परिणाम है:

['A (slow)', 'B (slower)', 'C (fast)']

यदि आप अपने वादों के वास्तविक निष्पादन की भी गारंटी देना चाहते हैं, तो आपको एक वादा कतार की तरह एक अवधारणा की आवश्यकता होगी। पी-कतार का उपयोग करके एक उदाहरण दिया गया है (सावधान रहें, आपको सभी कार्यों को पूरा करने की आवश्यकता है):

अनुक्रमिक वादा कतार

const PQueue = require('p-queue');
const queue = new PQueue({concurrency: 1});

// Thunked Promises:
const myPromises = [
  () => new Promise((resolve) => setTimeout(() => {
    resolve('A (slow)');
    console.log('A (slow)');
  }, 1000)),
  () => new Promise((resolve) => setTimeout(() => {
    resolve('B (slower)');
    console.log('B (slower)');
  }, 2000)),
  () => new Promise((resolve) => setTimeout(() => {
    resolve('C (fast)');
    console.log('C (fast)');
  }, 10))
];

queue.addAll(myPromises).then(console.log);

परिणाम

A (slow)
B (slower)
C (fast)

['A (slow)', 'B (slower)', 'C (fast)']

2
महान जवाब, स्पष्ट रूप से PQueue का उपयोग कर
आयरनस्टीन

मुझे एक अनुक्रमिक वादा कतार की आवश्यकता है, लेकिन यदि मुझे परिणामी sql रिकॉर्ड से इसे करना होगा तो यह कैसे होगा? इसके लिए? जबकि? ES2017 में कोई विकल्प नहीं है हमारा ES2018?
स्टैकडेव

PQueue ने मेरी मदद की! धन्यवाद! :)
पोडिग जूल

28

हां, मान resultsउसी क्रम में हैं जैसे कि promises

एक ES6 युक्ति काPromise.all हवाला दे सकता है , हालाँकि यह इस्तेमाल किए जाने वाले इटरी एपी और जेनेरिक वादा निर्माता के कारण थोड़ा जटिल है। हालाँकि, आप देखेंगे कि प्रत्येक रिज़ॉल्वर कॉलबैक में एक [[index]]विशेषता है जो वादा-सरणी पुनरावृत्ति में बनाई गई है और परिणाम सरणी पर मान सेट करने के लिए उपयोग की जाती है।


अजीब, मैंने आज एक यूट्यूब वीडियो देखा जिसमें कहा गया था कि आउटपुट ऑर्डर पहले से निर्धारित होता है जो हल किया गया, फिर दूसरा, फिर ..... मुझे लगता है कि वीडियो ओपी गलत था?
रॉय नमिर

1
@RoyiNamir: जाहिर तौर पर वह थे।
बर्गी

@ ओजिल वॉट? संकल्प का कालानुक्रमिक क्रम बिलकुल मायने नहीं रखता जब सभी वादे पूरे होते हैं। परिणाम सरणी में मानों का क्रम उसी प्रकार है जैसा कि वादों के इनपुट सरणी में है। यदि यह नहीं है, तो आपको एक उचित वादा लागू करना चाहिए।
बरगी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.