2016-08-18 25 views
11

आपके पास दो एसिंक विधि कॉल, बार और बाज़ के साथ एक प्रोटोटाइप ऑब्जेक्ट फू है।चेनिंग एसिंक विधि कॉल - जावास्क्रिप्ट

var bob = new Foo() 

Foo.prototype.bar = function land(callback) { 
    setTimeout(function() { 
    callback() 
    console.log('bar'); 
    }, 3000); 
}; 

Foo.prototype.baz = function land(callback) { 
    setTimeout(function() { 
    callback() 
    console.log('baz'); 
    }, 3000); 
}; 

हम bob.bar क्या करना चाहते हैं()। Baz() है और यह लोग इन "बार" और "baz" क्रमिक रूप से की है।

आप (अपने कॉलबैक समारोह में गुजर सहित) विधि कॉल संशोधित नहीं कर सकते हैं, तो आप इन विधि कॉल में एक डिफ़ॉल्ट कॉलबैक कैसे पारित कर सकते हैं?

कुछ विचार: डेकोरेटर के साथ

  1. लपेटें "बॉब"

  2. संशोधित निर्माता डिफ़ॉल्ट कॉलबैक आवंटित करने के लिए (अभी भी कैसे लागू करने पर फजी, एक छोटा सा उदाहरण इस्तेमाल कर सकते हैं), तो कोई भी सौंपा (राशि नहीं माना जाता है, तो यह संभव है या नहीं)

  3. एक जनरेटर आवरण है कि अगले विधि कॉल करने के लिए जब तक कोई भी छोड़ दिया जाता है के लिए जारी रहेगा प्रयोग करें?

+0

आप कैसे आप वादों का उपयोग, वह निर्दिष्ट कर सकते हैं? वे हुए लेकिन सुनिश्चित नहीं हैं कि वे –

+0

कैसे लागू करते हैं क्या आप 'bob.bar()। Baz()' वाक्यविन्यास से विवाहित हैं? ऑपरेशन को आपके वर्णन के कई तरीके हैं लेकिन मैं उस विशिष्ट वाक्यविन्यास के साथ काम करने वाली किसी भी चीज के बारे में नहीं सोच सकता। – Mike

+0

मान लें कि हम हैं :(मुझे लगता है कि हमें इसे किसी भी तरह से लपेटना है –

उत्तर

8

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

हम bob.bar क्या करना चाहते हैं()। Baz() है और यह लोग इन "बार" और "baz" क्रमिक रूप से की है।

आप इस bob.bar().baz() "वाक्यविन्यास" को प्राप्त करने के लिए ऐसा क्यों करना चाहते हैं? जब आप इसे सिंटैक्स काम करने के अतिरिक्त प्रयासों के बिना वादा एपीआई का उपयोग करके बहुत आसानी से कर सकते हैं जो वास्तव में कोड जटिलता को समझता है जिससे वास्तविक कोड को समझना मुश्किल हो जाता है।

Foo.prototype.bar = function() { 
    return new Promise(function (resolve) { 
     setTimeout(function() { 
      resolve() 
      console.log('bar'); 
     }, 3000); 
    }; 
}; 

Foo.prototype.baz = function() { 
    return new Promise(function (resolve) { 
     setTimeout(function() { 
      resolve() 
      console.log('baz'); 
     }, 3000); 
    }; 
}; 

अब आप यह करते हैं चाहते हैं:

तो, आप कुछ इस तरह वादा आधारित दृष्टिकोण है, जो अधिक से अधिक लचीलापन प्रदान करते हैं करता है कि आप अपने दृष्टिकोण के द्वारा प्राप्त होता है उपयोग करने पर विचार करना चाह सकते हैं उन्हें क्रमिक रूप से एक के बाद एक को चलाने के लिए:

var bob = new Foo(); 

bob.bar().then(function() { 
    return bob.baz(); 
}); 

// If you're using ES2015+ you could even do: 
bob.bar().then(() => bob.baz()); 

आप श्रृंखला के लिए और अधिक काम करता है की जरूरत है आप बस इसे कर सकता है:

bob.bar() 
    .then(() => bob.baz()) 
    .then(() => bob.anotherBaz()) 
    .then(() => bob.somethingElse()); 

वैसे भी, आप read this

+0

आपको कॉल सिंटैक्स को संशोधित करने की अनुमति नहीं है। – Bergi

0

करना चाह सकते हैं यदि आप वादों का उपयोग कर के लिए इस्तेमाल नहीं कर रहे हैं आप कॉलबैक नरक से बचने और रख अपने विवेक ES6 वादों कार्यात्मक प्रोग्रामिंग के लिए सबसे उपयुक्त तरीका हैं चाहते हैं। आप सिंक्रोनस टाइमलाइन में काम करने की तरह एसिंक्रोनस टाइमलाइन में अपने अनुक्रमिक एसिंक्रोनस कार्यों को बस चेन करते हैं।

इस विशेष मामले तुम सिर्फ अपने अतुल्यकालिक कार्यों promisify की जरूरत में

। मान लें कि आपके एसिंच फ़ंक्शन डेटा और कॉलबैक जैसे asynch(data,myCallback) लेते हैं। आइए मान लें कि कॉलबैक पहली बार त्रुटि है।

जैसे;

var myCallback = (error,result) => error ? doErrorAction(error) 
             : doNormalAction(result) 

जब आपका एसिंच फ़ंक्शन प्रोमोसिफाइड किया जाता है, तो आपको वास्तव में एक फ़ंक्शन वापस कर दिया जाएगा जो आपका डेटा लेता है और एक वादा करता है। आपको चरण पर myCallback लागू करने की उम्मीद है। myCallback का वापसी मूल्य अगले चरण में पारित किया जाएगा जहां आप myCallback के वापसी मूल्य के साथ प्रदान किए गए एक और एसिंच फ़ंक्शन का आह्वान कर सकते हैं और यह तब तक चलता है जब तक आपको आवश्यकता होती है। तो देखते हैं कि हम इस सार को आपके वर्कफ़्लो में कैसे कार्यान्वित करेंगे।

function Foo(){} 
 

 
function promisify(fun){ 
 
    return (data) => new Promise((resolve,reject) => fun(data, (err,res) => err ? reject(err) : resolve(res))); 
 
} 
 

 
function myCallback(val) { 
 
    console.log("hey..! i've got this:",val); 
 
    return val; 
 
} 
 

 
var bob = new Foo(); 
 

 
Foo.prototype.bar = function land(value, callback) { 
 
    setTimeout(function() { 
 
    callback(false,value*2); // no error returned but value doubled and supplied to callback 
 
    console.log('bar'); 
 
    }, 1000); 
 
}; 
 

 
Foo.prototype.baz = function land(value, callback) { 
 
    setTimeout(function() { 
 
    callback(false,value*2); // no error returned but value doubled and supplied to callback 
 
    console.log('baz'); 
 
    }, 1000); 
 
}; 
 

 
Foo.prototype.bar = promisify(Foo.prototype.bar); 
 
Foo.prototype.baz = promisify(Foo.prototype.baz); 
 

 
bob.bar(1) 
 
    .then(myCallback) 
 
    .then(bob.baz) 
 
    .then(myCallback)

+0

आपको अनुमति नहीं है कॉल वाक्यविन्यास को संशोधित करने के लिए। – Bergi

0

चेतावनी यह काफी सही अभी तक नहीं है। आदर्श रूप में हम वादा को उपclass करेंगे और उचित/पकड़ कार्यक्षमता प्राप्त करेंगे लेकिन bluebird Promise subclassing के साथ कुछ चेतावनी हैं। विचार वादा उत्पन्न करने वाले कार्यों की एक आंतरिक सरणी को स्टोर करना है, फिर जब वादा का इंतजार किया जाता है (तब/प्रतीक्षा करें) उन वादों पर क्रमशः प्रतीक्षा करें।

const Promise = require('bluebird'); 

class Foo { 
    constructor() { 
    this.queue = []; 
    } 

    // promise generating function simply returns called pGen 
    pFunc(i,pGen) { 
    return pGen(); 
    } 

    bar() { 
    const _bar =() => { 
     return new Promise((resolve,reject) => { 
     setTimeout(() => { 
      console.log('bar',Date.now()); 
      resolve(); 
     },Math.random()*1000); 
     })  
    } 
    this.queue.push(_bar); 
    return this; 
    } 

    baz() { 
    const _baz =() => { 
     return new Promise((resolve,reject) => { 
     setTimeout(() => { 
      console.log('baz',Date.now()); 
      resolve(); 
     },Math.random()*1000); 
     })  
    } 
    this.queue.push(_baz); 
    return this; 
    } 

    then(func) { 
    return Promise.reduce(this.queue, this.pFunc, 0).then(func); 
    } 
} 


const foo = new Foo(); 
foo.bar().baz().then(() => { 
    console.log('done') 
}) 

परिणाम:

[email protected]:~/Desktop/Dropbox/code/js/async-chain$ node index.js 
bar 1492082650917 
baz 1492082651511 
done 
संबंधित मुद्दे