सभी वादों के हल होने का इंतजार करें


107

इसलिए मेरे पास एक ऐसी स्थिति है जहां मेरे पास एक अज्ञात लंबाई की कई वादे श्रृंखलाएं हैं। मैं चाहता हूं कि सभी CHAINS संसाधित होने पर कुछ कार्रवाई हो। क्या यह भी संभव है? यहाँ एक उदाहरण है:

app.controller('MainCtrl', function($scope, $q, $timeout) {
    var one = $q.defer();
    var two = $q.defer();
    var three = $q.defer();

    var all = $q.all([one.promise, two.promise, three.promise]);
    all.then(allSuccess);

    function success(data) {
        console.log(data);
        return data + "Chained";
    }

    function allSuccess(){
        console.log("ALL PROMISES RESOLVED")
    }

    one.promise.then(success).then(success);
    two.promise.then(success);
    three.promise.then(success).then(success).then(success);

    $timeout(function () {
        one.resolve("one done");
    }, Math.random() * 1000);

    $timeout(function () {
        two.resolve("two done");
    }, Math.random() * 1000);

    $timeout(function () {
        three.resolve("three done");
    }, Math.random() * 1000);
});

इस उदाहरण में, मैंने $q.all()एक, दो, और तीन वादों की स्थापना की , जो कुछ यादृच्छिक समय में हल हो जाएंगे। मैं फिर एक और तीन के सिरों पर वादे जोड़ता हूं। मैं चाहता हूं कि allजब सभी जंजीरों का समाधान हो जाए तो मैं हल करूं । जब मैं यह कोड चलाता हूं तो यहां आउटपुट होता है:

one done 
one doneChained
two done
three done
ALL PROMISES RESOLVED
three doneChained
three doneChainedChained 

क्या जंजीरों को हल करने के लिए इंतजार करने का एक तरीका है?

जवाबों:


161

मैं चाहता हूं कि सभी तब हल करें जब सभी जंजीरों को सुलझा लिया गया हो।

यकीन है, तो बस all()प्रारंभिक वादों के बजाय प्रत्येक श्रृंखला का वादा पारित करें :

$q.all([one.promise, two.promise, three.promise]).then(function() {
    console.log("ALL INITIAL PROMISES RESOLVED");
});

var onechain   = one.promise.then(success).then(success),
    twochain   = two.promise.then(success),
    threechain = three.promise.then(success).then(success).then(success);

$q.all([onechain, twochain, threechain]).then(function() {
    console.log("ALL PROMISES RESOLVED");
});

2
मेरे सबसे बुरे डर की पुष्टि करने के लिए धन्यवाद। अब मुझे आखिरी वादा करने का एक तरीका आना चाहिए।
१ .

उससे क्या दिक्कत है? क्या आपकी चेन गतिशील रूप से निर्मित हैं?
बरगी

बिल्कुल मेरी समस्या। मैं गतिशील रूप से एक वादा श्रृंखला बनाने की कोशिश कर रहा हूं तब मैं कुछ करना चाहता हूं जब श्रृंखला पूरी हो जाए।
जेनसेगर

क्या आप हमें अपना कोड दिखा सकते हैं (शायद एक नया प्रश्न पूछें)? क्या Q.allनिष्पादित किए जाने के बाद श्रृंखला में आइटम जोड़े गए हैं - अन्यथा यह तुच्छ होना चाहिए?
बरगी

मैं आपको कोड दिखाना पसंद करूंगा ... लेकिन मैंने इसे अभी तक लिखना नहीं छोड़ा है, हालांकि मैं इसे समझाने की पूरी कोशिश करूंगा। मेरे पास "कार्यों" की एक सूची है जिसे करने की आवश्यकता है। इन क्रियाओं में उनके साथ संबद्ध उप-क्रियाओं का कोई भी स्तर हो सकता है। मैं चाहता हूं कि जब सभी क्रियाएं और उनके सबटक्शन पूरे हो जाएं तो मैं कुछ कर पाऊंगा। संभावित रूप से कई $q.alls होंगे, हालाँकि एक बार जब मैं रिज़ॉल्यूशन प्रक्रिया शुरू करूँगा, तो कोई भी नई कार्यवाही / वादे जंजीर नहीं होंगे।
जेंसेगर

16

स्वीकार किए जाते हैं जवाब सही है। मैं उन लोगों के लिए थोड़ा विस्तार करने के लिए एक उदाहरण प्रदान करना चाहता हूं जो परिचित नहीं हैं promise

उदाहरण:

मेरे उदाहरण में, मुझे सामग्री को रेंडर करने से पहले उपलब्ध होने srcपर imgटैग की विशेषताओं को अलग-अलग दर्पण के साथ बदलने की आवश्यकता है।

var img_tags = content.querySelectorAll('img');

function checkMirrorAvailability(url) {

    // blah blah 

    return promise;
}

function changeSrc(success, y, response) {
    if (success === true) {
        img_tags[y].setAttribute('src', response.mirror_url);
    } 
    else {
        console.log('No mirrors for: ' + img_tags[y].getAttribute('src'));
    }
}

var promise_array = [];

for (var y = 0; y < img_tags.length; y++) {
    var img_src = img_tags[y].getAttribute('src');

    promise_array.push(
        checkMirrorAvailability(img_src)
        .then(

            // a callback function only accept ONE argument. 
            // Here, we use  `.bind` to pass additional arguments to the
            // callback function (changeSrc).

            // successCallback
            changeSrc.bind(null, true, y),
            // errorCallback
            changeSrc.bind(null, false, y)
        )
    );
}

$q.all(promise_array)
.then(
    function() {
        console.log('all promises have returned with either success or failure!');
        render(content);
    }
    // We don't need an errorCallback function here, because above we handled
    // all errors.
);

स्पष्टीकरण:

AngularJS डॉक्स से :

thenविधि:

तब (सक्सेसकॉलबैक, एरर कलैकबैक, नोटिफ़कबैक) - चाहे जब वादा किया गया था या हल किया जाएगा या खारिज कर दिया जाएगा, तो परिणाम के उपलब्ध होते ही सफलता या त्रुटि कॉलबैक में से किसी एक को कॉल करें। कॉलबैक को एकल तर्क के साथ कहा जाता है : परिणाम या अस्वीकृति का कारण।

$ Q.all (वादों)

एक से अधिक वादों में कई वादों को मिलाता है जो हल किए जाते हैं जब सभी इनपुट वादों को हल किया जाता है।

promisesपरम वादों की एक सरणी हो सकता है।

के बारे में bind(), अधिक जानकारी यहाँ: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind


की thenविधि को $q.allदिए गए वादों की एक सरणी प्रदान की जाती है, इसलिए आप उस सरणी को लूप कर सकते हैं और सरणी में thenप्रत्येक आइटम पर कॉल कर सकते हैं , जैसा कि thenजब आप वादे को जोड़ते हैं तो कॉल करने का विरोध करते हैं promise_array
निक

4

हाल ही में यह समस्या थी लेकिन वादों की संख्या के साथ । jQuery.map () का उपयोग करके ।

function methodThatChainsPromises(args) {

    //var args = [
    //    'myArg1',
    //    'myArg2',
    //    'myArg3',
    //];

    var deferred = $q.defer();
    var chain = args.map(methodThatTakeArgAndReturnsPromise);

    $q.all(chain)
    .then(function () {
        $log.debug('All promises have been resolved.');
        deferred.resolve();
    })
    .catch(function () {
        $log.debug('One or more promises failed.');
        deferred.reject();
    });

    return deferred.promise;
}

यह jQuery.map () नहीं है, लेकिन Array.prototype.map () ( developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… ) है, लेकिन यह दृष्टिकोण काम करता है।
अनस्तासिया 23

0

एक रास्ता है। $q.all(...

आप नीचे दिए गए सामान की जांच कर सकते हैं:

http://jsfiddle.net/ThomasBurleson/QqKuk/

http://denisonluz.com/blog/index.php/2013/10/06/angularjs-returning-multiple-promises-at-once-with-q-all/


हालांकि मुझे अपनी श्रृंखला की लंबाई जानना सही है? मेरा मतलब है कि अगर मेरे पास 10 का वादा था, तो मुझे $q.all([p1.then(..).then(...).then(...).then(...) ...]);सही करना होगा?
जेंसेगर

0

आप "async फ़ंक्शन" में "प्रतीक्षा" का उपयोग कर सकते हैं ।

app.controller('MainCtrl', async function($scope, $q, $timeout) {
  ...
  var all = await $q.all([one.promise, two.promise, three.promise]); 
  ...
}

ध्यान दें: मैं 100% सुनिश्चित नहीं हूं कि आप एक गैर- async फ़ंक्शन से एक async फ़ंक्शन को कॉल कर सकते हैं और सही परिणाम दे सकते हैं।

यह कहा कि यह कभी एक वेबसाइट पर इस्तेमाल नहीं किया जाएगा। लेकिन लोड-परीक्षण / एकीकरण परीक्षण के लिए ... हो सकता है।

उदाहरण कोड:

async function waitForIt(printMe) {
  console.log(printMe);
  console.log("..."+await req());
  console.log("Legendary!")
}

function req() {
  
  var promise = new Promise(resolve => {
    setTimeout(() => {
      resolve("DARY!");
    }, 2000);
    
  });

    return promise;
}

waitForIt("Legen-Wait For It");

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.