2016-01-07 24 views
9

जब कोई वादे की श्रृंखला में देरी हो सकती है तो एक वादे में देरी कैसे करें? मुझे इसकी आवश्यकता है क्योंकि मैं स्क्रिप्ट के साथ जाने से पहले एक सीएसएस एनीमेशन पूरा करने के लिए इंतजार करना चाहता हूं।फ़ंक्शन

फ़ंक्शन का उद्देश्य एक दृश्य खोलना है। यदि दृश्य पहले से खुला नहीं है, तो इसे खोलें (कक्षा को बदलकर), सीएसएस एनीमेशन के लिए प्रतीक्षा करें, आगे बढ़ें। यदि दृश्य पहले से खुला है, तो कुछ भी नहीं करें और आगे बढ़ें।

मैं इस तरह समारोह कॉल करना चाहते हैं:

$scope.openView(viewId).then(function() {    
    $scope.openAnotherView(anotherViewId); 
}); 


/** Function to open some view **/ 
$scope.openView = function (viewId) { 
    function timeout(delay) { 
     return new Promise(function(resolve, reject) { 
      $timeout(resolve, delay); 
     }); 
    } 

    // Check if view is already open 
    if ($scope.viewId != viewId) { 
     $scope.viewId = viewId;    

     // get data from ajaxcall (also a promise) 
     return MyService.getData(viewId).then(function(data) { 
      // add data to view 
      // change class to open view 
      // this is working ok! 
     }).then(function() { 
      return timeout(30000 /* some large number (testing purpose) */) 
     }); 
    } else { 
     // view is already open, so return here we don't have to wait 
     // return empty promise, with no timeout 
     return new Promise(function(resolve, reject) { 
      resolve() 
     });  
    } 
} 

इस कोड काम करता है (यह एक कोणीय नियंत्रक के भीतर एक समारोह है), लेकिन देरी से काम नहीं कर रहा है। क्या मेरा दृष्टिकोण ठीक है? मुझे यहां क्या समझ नहीं आ रहा है?


संपादित करें 1: @sdgluck से सुझाव के साथ कोड में सुधार


संपादित 2:

मुख्य प्रश्न एक स्पष्ट करने के लिए: मुख्य प्रश्न में से कुछ स्पष्टीकरण थोड़ा और: क्या मैं इस कोड का उपयोग अपने कोड में कर सकता हूं?

// code doesnt know wheter to wait or not 
// can the Promise do this? 
openView().then(function() {    
    openAnotherView(); 
} 

परिणाम 1:

ब्राउज़र openView() फोन करेगा लेकिन जब से यह पहले से खुला है यह सिर्फ openAnotherView() तुरंत (कोई देरी) कॉल करेंगे।

परिणाम 2:

दृश्य खुला, तो openView() यह खुल जाएगा, तो एक देरी (? या के रूप में @Dominic टोबियास बताते हैं, एक eventlister जोड़ें) तो openAnotherView() कुछ विलंब के बाद फोन नहीं है।

किसी भी मदद के लिए धन्यवाद!

संपादित 3: समस्या के साथ एक बेला जोड़ा http://jsfiddle.net/C3TVg/60/

+1

मुझे लगता है कि आप इस गलत तरीके से जा रहे हैं। ऐसा लगता है कि आप यह जानना चाहेंगे कि एनीमेशन [इस] (https://davidwalsh.name/css-animation-callback) की तरह पूरा हो गया है या नहीं। –

उत्तर

1

मैं वादों की एक श्रृंखला में देरी कैसे कर सकता हूं?

$timeout एक वादा देता है। रिटर्न जो श्रृंखला पर वादा करता है।

$scope.openView = function (viewId) { 
    // Check if view is already open 
    if ($scope.viewId == viewId) { 
     //chain right away with empty promise 
     return $q.when(); 
    }; 

    //otherwise if view is not already open 

    var p = MyService.getData(viewId).then(function(data) { 
      // add data to view 
      // change class to open view 
      // this is working ok! 
    }); 

    var pDelayed = p.then (function() { 
     //return to chain delay 
     return $timeout(angular.noop, 30000); 
     }); 

    //return delayed promise for chaining 
    return pDelayed; 
}; 

$scope.openView(viewId).then(function() { 
    //use chained promise    
    $scope.openAnotherView(anotherViewId); 
}); 
+0

Thx, मैंने अभी अपना प्रश्न अपडेट किया है। मैंने इस तथ्य को स्पष्ट करने की कोशिश की कि अगर मुझे इंतजार करना है तो मैं पहले से नहीं हूं। सशर्त देरी जोड़ने के लिए – 11mb

+0

अपडेट किया गया। – georgeawg

3

प्रत्येक then accepts a function जो एक वादा लौटना चाहिए की व्याख्या की। यह वादा का एक उदाहरण स्वीकार नहीं करता है। आप timeout करने के लिए कॉल वापस करना चाहते:

return MyService 
    .getData(viewId) 
    .then(function(data) { 
     // ... 
    }) 
    .then(function() { 
     return timeout(3000); 
    }); 

वैकल्पिक रूप से, timeout मुनाफा होता है एक वादा करने के बजाय एक समारोह:

function timeout(delay) { 
    return function() { 
     return new Promise(function(resolve, reject) { 
      //      ^^^^^^^ (misspelt in your example) 
      $timeout(resolve, delay); 
     }); 
    }; 
} 

और फिर आप अपने उदाहरण के रूप में इसका इस्तेमाल कर सकते हैं:

return MyService 
    .getData(viewId) 
    .then(function(data) { 
     // ... 
    }) 
    .then(timeout(3000)); 
+0

थैक्स फ़ंक्शन के साथ मेरी गलती की पहचान करने और इसे हल करने के तरीके को साफ़ करने के लिए Thx। लेकिन मुझे लगता है कि मेरे कोड के साथ एक और मुद्दा है जैसे @ डोमिनिक टोबीस इंगित कर रहा है। – 11mb

+1

@ 11 एमबी कोई समस्या नहीं। और हाँ, दूसरा जवाब अधिक व्यापक है। :-) – sdgluck

13

एक वादे देरी करने के लिए, बस प्रतीक्षा समय के बाद resolve फ़ंक्शन पर कॉल करें।मुझे डर लग रहा है कि नहीं कैसे है -

new Promise(function(resolve, reject) { 
    setTimeout(function() { 
    resolve(); 
    }, 3000); // Wait 3s then resolve. 
}); 

अपने कोड के साथ मुद्दा यह है कि आप एक वादा लौट रहे हैं और फिर उस वादा की then अंदर आप एक दूसरे से पैदा कर रहे है और इसके लिए प्रतीक्षा करने के लिए मूल वादा उम्मीद है काम का वादा करता है। आप वादा समारोह के अंदर अपने सभी इंतज़ार कर क्या करना है और उसके बाद संकल्प कहेंगे:

संपादित करें: यह सच नहीं है, तो आप वादा श्रृंखला किसी भी then में देरी कर सकते हैं:

function promise1() { 
 
    return new Promise((resolve) => { 
 
    setTimeout(() => { 
 
     console.log('promise1'); 
 
     resolve(); 
 
    }, 1000); 
 
    }) 
 
    .then(promise2); 
 
} 
 

 
function promise2() { 
 
    return new Promise((resolve) => { 
 
    setTimeout(() => { 
 
     console.log('promise2'); 
 
     resolve(); 
 
    }, 1000); 
 
    }); 
 
} 
 

 
function promise3() { 
 
    return new Promise((resolve) => { 
 
    setTimeout(() => { 
 
     console.log('promise3'); 
 
     resolve(); 
 
    }, 1000); 
 
    }); 
 
} 
 

 
promise1() 
 
    .then(promise3) 
 
    .then(() => { 
 
    console.log('...finished'); 
 
    })

हालांकि यह एक सीएसएस एनीमेशन की प्रतीक्षा करने का एक अच्छा तरीका नहीं है। यह transitionend घटना को सुनने के लिए बेहतर है:

element.addEventListener('transitionend', onTransitionEnd); 
element.classList.add('transition-me'); 

नोट आप एक animation इसी अवधारणा उपयोग कर रहे हैं के बजाय एक transition की लेकिन animationend घटना का उपयोग लागू होता है।

+0

'$ टाइमआउट' से 'setTimeout' का उपयोग करना _delay को हल नहीं करता है, कार्य नहीं कर रहा है। लेकिन संक्रमण के लिए इंतजार कैसे करें इस बारे में अच्छी सलाह। :-) – sdgluck

+0

आह, मैं वास्तव में सीएसएस और जेएस में एनीमेशन/संक्रमण-समय डुप्लीकेट होने से नापसंद हूं। मैं निश्चित रूप से उसमें देख लूंगा! आपके सुझाव के बारे में: यदि मैं 'देखने के लिए डेटा जोड़ें' के आसपास एक टाइमआउट जोड़ता हूं-कार्यक्षमता और अब यह मेरा दृश्य खोलने से पहले इंतजार कर रहा है, लेकिन यह पहले के कॉलिंग में देरी नहीं करता है ('सबकुछ तैयार है') और दूसरा फिर ('openAnotherView')। मैंने इस तरह हल किया: Promise.resolve(); – 11mb

+0

तो आप एक वादा वापस करना चाहते हैं लेकिन आप इसे इंतजार नहीं करना चाहते हैं? –