2013-04-09 5 views
5

मैं एक ऐसा ऐप लिख रहा हूं जो ऐप्पल से रिसेप्ट को सत्यापित करने के लिए बात करता है। उनके पास एक सैंडबॉक्स और उत्पादन यूआरएल है जिसे आप पोस्ट कर सकते हैं।नेस्टेड वादे के साथ स्वच्छ कोड लिखना

ऐप्पल के साथ संवाद करते समय, यदि आपको 21007 स्थिति मिलती है, तो इसका मतलब है कि आप उत्पादन यूआरएल पर पोस्ट कर रहे थे, जब आपको सैंडबॉक्स में पोस्ट करना चाहिए।

इसलिए मैंने पुनः प्रयास तर्क को सुविधाजनक बनाने के लिए कुछ कोड लिखा। यहाँ मेरी कोड का एक सरलीकृत संस्करण है:

var request = require('request') 
    , Q = require('q') 
    ; 

var postToService = function(data, url) { 
    var deferred = Q.defer(); 
    var options = { 
    data: data, 
    url: url 
    }; 

    request.post(options, function(err, response, body) { 
    if (err) { 
     deferred.reject(err); 
    } else if (hasErrors(response)) { 
     deferred.reject(response); 
    } else { 
     deferred.resolve(body); 
    } 
    }); 

    return deferred.promise; 
}; 

exports.verify = function(data) { 
    var deferred = Q.defer(); 

    postToService(data, "https://production-url.com") 
    .then(function(body) { 
     deferred.resolve(body); 
    }) 
    .fail(function(err) { 
     if (err.code === 21007) { 
     postToService(data, "https://sandbox-url.com") 
      .then(function(body){ 
      deferred.resolve(body); 
      }) 
      .fail(function(err) { 
      deferred.reject(err); 
      }); 
     } else { 
     deferred.reject(err); 
     } 

    }); 

    return deferred.promise; 
}; 

की पुष्टि समारोह में पुन: प्रयास करें भाग बहुत बदसूरत और एकत्रित किए गए वादे के पढ़ने के लिए मुश्किल है। क्या ऐसा करने का कोई बेहतर तरीका है?

+0

एक विचार यह है कि मन में आता है आइस्ड CoffeeScript जिसके लिए निरंतरता-गुजर (सी # के async के समान/इंतजार है) वाक्यात्मक समर्थन हासिल है उपयोग कर रहा है: http://maxtaco.github.io/coffee-script /। दुर्भाग्य से इसे कॉफीस्क्रिप्ट का उपयोग करने की आवश्यकता होगी, और इसके "गैर-मानक" संस्करण की आवश्यकता होगी जो कि बदमाश और इस तरह समर्थित नहीं है। – millimoose

उत्तर

5

आपको एक त्रुटि अस्वीकृति हैंडलर में वादा खारिज जारी रखने के लिए फिर से फेंक सकते हैं, या आप एक नया अस्वीकृति को बदलने के लिए वादा लौट सकते हैं।

exports.verify = function(data) { 
    return postToService(data, "https://production-url.com") 
    .fail(function(err) { 
     if (err.code === 21007) { 
     return postToService(data, "https://sandbox-url.com") 
     } else { 
     throw err 
     } 
    }); 
}; 
+0

मुझे यह पसंद है। अच्छा, साफ और सरल! – Anton

0

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

exports.verify = function(data) { 
    var deferred = Q.defer(); 

    postToService(data, "https://production-url.com") 

    .then(deferred.resolve, function(err) { 

     if (err.code === 21007) { 

     postToService(data, "https://sandbox-url.com") 

      .then(deferred.resolve, deferred.reject); 

     } else { deferred.reject(err); } 

    }); 

return deferred.promise; 
}; 
1

यहां कुछ संभावनाएं हैं। चूंकि इस प्रश्न में व्यक्तिगत स्वाद का एक तत्व है, इसलिए आप जो देख रहे हैं उसे पसंद या नहीं कर सकते!

resolve और reject के लिए एक आवरण का प्रयोग करें - -

विकल्प 1 (प्रवेश मैं इस कोड परीक्षण नहीं किया)। यह सहायक कार्यों के रूप में 'शोर' जोड़ता है, लेकिन शेष को साफ करता है।

var resolve = function (deferred, ob) { 
    return function() { 
    deferred.resolve(ob); 
    }; 
}; 

var reject = function (deferred, ob) { 
    return function() { 
    deferred.reject(ob); 
    }; 
}; 

exports.verify = function(data) { 
    var deferred = Q.defer(); 

    postToService(data, "https://production-url.com") 
    .then(resolve(deferred, body)) 
    .fail(function(err) { 
     if (err.code === 21007) { 
     postToService(data, "https://sandbox-url.com") 
      .then(resolve(deferred, body)) 
      .fail(reject(deferred, err)); 
     } else { 
     deferred.reject(err); 
     } 
    }); 

    return deferred.promise; 
}; 

विकल्प 2 - बांध का उपयोग करें। इसका मौजूदा जेएस कार्यक्षमता का उपयोग करने का लाभ है, लेकिन कॉलबैक बनाते समय आपके पास deferred पर डुप्लिकेट संदर्भ हैं।

exports.verify = function(data) { 
    var deferred = Q.defer(); 

    postToService(data, "https://production-url.com") 
    .then(deferred.resolve.bind(deferred, body)) 
    .fail(function(err) { 
     if (err.code === 21007) { 
     postToService(data, "https://sandbox-url.com") 
      .then(deferred.resolve.bind(deferred, body)) 
      .fail(deferred.reject.bind(deferred, err)); 
     } else { 
     deferred.reject(err); 
     } 
    }); 

    return deferred.promise; 
}; 

विकल्प 3 - बाइंड और 'विधि हैंडल' का उपयोग करें (# 2 पर मामूली बदलाव)।

exports.verify = function(data) { 
    var deferred = Q.defer(); 
    var resolve = deferred.resolve; 
    var reject = deferred.reject; 

    postToService(data, "https://production-url.com") 
    .then(resolve.bind(deferred, body)) 
    .fail(function(err) { 
     if (err.code === 21007) { 
     postToService(data, "https://sandbox-url.com") 
      .then(resolve.bind(deferred, body)) 
      .fail(reject.bind(deferred, err)); 
     } else { 
     deferred.reject(err); 
     } 
    }); 

    return deferred.promise; 
}; 

विकल्प 4 - बंदर पैच स्थगित।

function patch(deferred) { 
    deferred.resolveFn = function (ob) { 
    return function() { 
     deferred.resolve(ob); 
    }; 
    }; 
    deferred.rejectFn = function (ob) { 
    return function() { 
     deferred.reject(ob); 
    }; 
    }; 
    return deferred; 
} 

exports.verify = function(data) { 
    var deferred = patch(Q.defer()); 

    postToService(data, "https://production-url.com") 
    .then(deferred.resolveFn(body)) 
    .fail(function(err) { 
     if (err.code === 21007) { 
     postToService(data, "https://sandbox-url.com") 
      .then(deferred.resolveFn(body)) 
      .fail(deferred.rejectFn(err)); 
     } else { 
     deferred.reject(err); 
     } 
    }); 

    return deferred.promise; 
}; 
0

स्टुअर्ट का जवाब सही है, बिंदु श्रृंखला के वादे के लिए था। और मैं यह स्पष्ट करना चाहता हूं कि केवल लपेटने के लिए Q.defer का उपयोग करने की आवश्यकता नहीं है। इसे एक विरोधी पैटर्न भी माना जाता है। यहाँ कारण देखें The Deferred anti-pattern

var request = require('request') 
    , Q = require('q'); 

var PRODUCTION_URL = "https://production-url.com", 
var SANDBOX_URL = "https://sandbox-url.com", 


export.verify = function() { 

    return postToProduction(data) 
     .fail(function(error) { 
      if (error.code === 21007) return postToSanbox(data); 
      throw error; 
     }); 
} 

function postToProduction(data) { 
    return postToService(data, PRODUCTION_URL); 
} 

function postToSandbox(data) { 
    return postToService(data, SANDBOX_URL); 
} 

function postToService(data, url) { 
    var deferred = Q.defer(); 

    var options = { 
     data: data, 
     url: url 
    }; 

    request.post(options, function(err, response, body) { 
    if (err) return deferred.reject(err); 
    if (hasErrors(response)) return deferred.reject(response); 

    deferred.resolve(body);  
    }); 

    return deferred.promise; 
} 
+0

आप 'Q.ninvoke' (और वाणिज्य) का उपयोग कर स्थगित से पूरी तरह से बच सकते हैं – Bergi

संबंधित मुद्दे