2010-01-29 13 views
13

मैं this article पढ़ रहा हूं और वादा अबास्ट्रक्शन पर अनुभाग मुझे थोड़ा अधिक जटिल लगता है। निम्नलिखित एक उदाहरण के रूप में दिया जाता है:कॉमनजेएस में 'वादे' अमूर्तता का क्या फायदा है?

requestSomeData("http://example.com/foo") // returns a promise for the response 
    .then(function(response){ // ‘then’ is used to provide a promise handler 
     return JSON.parse(response.body); // parse the body 
    }) // returns a promise for the parsed body 
    .then(function(data){ 
     return data.price; // get the price 
    }) // returns a promise for the price 
    .then(function(price){ // print out the price when it is fulfilled 
     print("The price is " + price); 
    }); 

ऐसा नहीं है कि निम्नलिखित कोड के कम लाइनों के साथ एक ही परिणाम प्रदान कर सकता है मुझे लगता है:

requestSomeData("http://example.com/foo") 
    .requestHandler(function(response){ 
     // parse the body 
     var data = JSON.parse(response.body); 

     // get the price 
     var price = data.price; 

     // print out the price 
     print("The price is " + price); 
    }); 
+2

आप सही हैं, सिंक्रोनस ऑपरेशंस के लिए वादे का उपयोग करने में कोई बात नहीं है। तो परिणाम बराबर होना चाहिए। लेकिन फिर यह एक उदाहरण है और वादे के उपयोग के लिए दिखाता है। आपके उदाहरण के बाद चल रहे कोड के लिए वास्तव में एक अंतर है। यदि आपको उदाहरण के बाद कुछ चलाने की आवश्यकता है, तो आप इसे कर सकते हैं (वादा दृष्टिकोण का उपयोग करके) उदाहरण कोड क्या कर रहा है इसके बारे में कुछ भी जानने के बिना –

उत्तर

17

हालांकि यह सच है कि दोनों अंततः पूरा होगा वही बात, अंतर यह है कि आपका दूसरा उदाहरण असीमित नहीं है। उदाहरण के लिए, विचार करें कि क्या होता है यदि JSON.parse(...) एक बेहद महंगी ऑपरेशन बन जाता है; आपको तब तक लटकना होगा जब तक कि सब कुछ खत्म नहीं हो जाता है, जो हमेशा आप जो चाहते हैं वह हमेशा नहीं हो सकता है।

यही वादा आपको प्राप्त करता है: एक अधिक सुविधाजनक समय तक सही उत्तर की गणना को स्थगित करने की शक्तिशाली क्षमता। जैसा कि नाम से पता चलता है, निर्माण "वादे" आपको किसी बिंदु पर परिणाम देने के लिए, अभी जरूरी नहीं है। आप वायदा और वादे के बारे में अधिक पढ़ सकते हैं बड़े पैमाने पर here पर काम करते हैं।

+2

यहां एक सुविधाजनक समय क्या है? यदि ऑपरेशन बेहद महंगा है और JSON.parse जावास्क्रिप्ट कोड का एक टुकड़ा है तो यह वैसे भी लटका होगा। अंतर केवल इतना है कि वादे के साथ आप वास्तव में चल रहे कार्यों को पूरा कर सकते हैं। –

+3

यह सच है कि पार्सिंग एक ही समय ले जाएगा चाहे यह समकालिक रूप से या असीमित रूप से गणना की जाती है। हालांकि, यदि आप अपने पार्सर को इस तरह से लागू करने के लिए समय लेते हैं कि यह अनुमान लगाया जाता है कि ऑपरेशन के छोटे टुकड़े पूरा करने के बाद यह घटना लूप को उत्पन्न करता है, तो अन्य एसिंक्रोनस कोड प्रत्येक खंड के बीच असीमित रूप से चला सकता है। यह एक आवेदन को अधिक उत्तरदायी बनाता है, तेज़ नहीं। –

+0

या JSON.parse एक मूल विधि हो सकता है और किसी अन्य थ्रेड पर निष्पादित हो सकता है – Jan

3

के एक शुद्ध जावास्क्रिप्ट उदाहरण के लिए वादा उदाहरण तुलना करते हैं:

// First we need a convenience function for W3C's fiddly XMLHttpRequest. 
// It works a little differently from the promise framework. Instead of 
// returning a promise to which we can attach a handler later with .then(), 
// the function accepts the handler function as an argument named 'callback'. 

function requestSomeDataAndCall(url, callback) { 
    var req = new XMLHttpRequest(); 
    req.onreadystatechange = resHandler; 
    req.open("GET", url, false); 
    req.send(); 
    function resHandler() { 
     if (this.readyState==4 && this.status==200) { 
      callback(this); 
     } else { 
      // todo: Handle error. 
     } 
    } 
} 

requestSomeDataAndCall("http://example.com/foo", function(res){ 
    setTimeout(function(){ 
     var data = JSON.parse(res.responseText); 
     setTimeout(function(){ 
      var price = data.price; 
      setTimeout(function(){ 
       print("The price is "+price); 
      },10); 
     },10); 
    },10); 
}); 

के रूप में नॉर्बर्ट हार्टल ने कहा, JSON.parse() ब्राउज़र बड़ी स्ट्रिंग्स के लिए रखती हूँ। तो मैंने अपने निष्पादन में देरी (10 मिलीसेकंड के विराम के बाद) में सेटटाइमआउट() का उपयोग किया। यह क्रिस कौवाल के समाधान का एक उदाहरण है। यह वर्तमान जावास्क्रिप्ट थ्रेड को पूरा करने की अनुमति देता है, ब्राउज़र को डीओएम परिवर्तन प्रस्तुत करने के लिए मुक्त करता है और कॉलबैक चलाने से पहले उपयोगकर्ता के लिए पृष्ठ स्क्रॉल करता है।

मुझे उम्मीद है कि आमज वादा ढांचा सेटटाइमआउट जैसे कुछ भी उपयोग करता है, अन्यथा लेख के उदाहरण में बाद के वादे वास्तव में डर के रूप में सिंक्रनाइज़ रूप से चलेंगे।

ऊपर मेरा विकल्प बहुत बदसूरत दिखता है, बाद की प्रक्रियाओं के साथ आगे इंडेंटेशन की आवश्यकता होती है। मैं, कोड का पुनर्गठन ताकि हम सभी एक स्तर में हमारी प्रक्रिया श्रृंखला प्रदान कर सकते हैं:

function makeResolver(chain) { 
    function climbChain(input) { 
     var fn = chain.shift();  // This particular implementation 
     setTimeout(function(){  // alters the chain array. 
      var output = fn(input); 
      if (chain.length>0) { 
       climbChain(output); 
      } 
     },10); 
    } 
    return climbChain; 
} 

var processChain = [ 
    function(response){ 
     return JSON.parse(response.body); 
    }, 
    function(data){ 
     return data.price; // get the price 
    }, 
    function(price){ 
     print("The price is " + price); 
    } 
]; 

var climber = makeResolver(promiseChain); 
requestSomeDataAndCall("http://example.com/foo", climber); 

मैं जावास्क्रिप्ट में कॉलबैक की है कि पारंपरिक आगे गुजर प्रदर्शित करने के लिए उम्मीद कर रही थी वादे करने के लिए काफी बराबर है। हालांकि, मूल उदाहरण में कोड की नीरसता के संदर्भ में, मैंने दो प्रयासों के बाद दिखाया है कि वादे एक बहुत ही सुरुचिपूर्ण समाधान हैं!

0

कोई यह भी जोड़ सकता है कि दूसरे संस्करण के पहले संस्करण का लाभ यह है कि यह परिष्करण श्रृंखला में अलग-अलग संचालन को अलग करता है (कार्यों को जगह में भी लिखा जाना नहीं है)। दूसरा संस्करण अनुप्रयोग तर्क के साथ निम्न-स्तरीय पार्सिंग दोनों को मिश्रित करता है। विशेष रूप से, दिशानिर्देशों के रूप में SOLID सिद्धांतों का उपयोग करके, दूसरा संस्करण OCP और SRP दोनों का उल्लंघन करता है।

1

दूसरा स्निपेट सेवा हमले से इनकार करने के लिए कमजोर है क्योंकि example.com/foo सर्वर को क्रैश करने के लिए अमान्य जेसन वापस कर सकता है। यहां तक ​​कि खाली प्रतिक्रिया भी अवैध JSON (हालांकि वैध जेएस) है। यह mysql_* उदाहरण एसक्यूएल इंजेक्शन छेद चमकाने के साथ उदाहरण है।

और वादा कोड भी बेहतर किया जा सकता है।ये बराबर हैं:

requestSomeData("http://example.com/foo") // returns a promise for the response 
    .then(function(response){ // ‘then’ is used to provide a promise handler 
     // parse the body 
     var data = JSON.parse(response.body); 

     // get the price 
     var price = data.price; 

     // print out the price 
     print("The price is " + price); 
    }); 

और: यदि हम त्रुटि को संभालने के लिए चाहता था

requestSomeData("http://example.com/foo") 
    .requestHandler(function(response){ 
     try { 
      var data = JSON.parse(response.body); 
     } 
     catch(e) { 
      return; 
     } 

     // get the price 
     var price = data.price; 

     // print out the price 
     print("The price is " + price); 
    }); 

, तो इन बराबर होगा:

requestSomeData("http://example.com/foo") // returns a promise for the response 
    .then(function(response){ // ‘then’ is used to provide a promise handler 
     // parse the body 
     var data = JSON.parse(response.body); 

     // get the price 
     var price = data.price; 

     // print out the price 
     print("The price is " + price); 
    }).catch(SyntaxError, function(e) { 
     console.error(e); 
    }); 

और:

requestSomeData("http://example.com/foo") 
    .requestHandler(function(response){ 
     try { 
      var data = JSON.parse(response.body); 
     } 
     catch(e) { 
      //If the above had a typo like `respons.body` 
      //then without this check the ReferenceError would be swallowed 
      //so this check is kept to have as close equality as possible with 
      //the promise code 
      if(e instanceof SyntaxError) { 
       console.error(e); 
       return; 
      } 
      else { 
       throw e; 
      } 
     } 

     // get the price 
     var price = data.price; 

     // print out the price 
     print("The price is " + price); 
    });