2012-10-19 20 views
42

एंबर-data.js: https://github.com/emberjs/data/tree/0396411e39df96c8506de3182c81414c1d0eb981Ember.js डेटा RESTAdapter का उपयोग करते समय त्रुटियों को कैसे संभाला जाना चाहिए?

संक्षेप में, जब वहाँ एक त्रुटि है, मैं ध्यान में रखते हुए त्रुटि संदेश प्रदर्शित करना चाहते हैं, और उसके बाद उपयोगकर्ता कर सकते हैं 1) रद्द, जो लेन-देन 2 रोलबैक होगा) को ठीक करें इनपुट त्रुटियों और सर्वर पर मान्यताओं को पारित, सफलतापूर्वक लेनदेन प्रतिबद्ध।

नीचे स्रोत से एक कोड स्निपेट है। इसमें त्रुटि कॉलबैक शामिल नहीं है।

updateRecord: function(store, type, record) { 
    var id = get(record, 'id'); 
    var root = this.rootForType(type); 

    var data = {}; 
    data[root] = this.toJSON(record); 

    this.ajax(this.buildURL(root, id), "PUT", { 
    data: data, 
    context: this, 
    success: function(json) { 
     this.didUpdateRecord(store, type, record, json); 
    } 
    }); 
}, 

कुल मिलाकर, सर्वर से त्रुटि प्राप्त करने और दृश्य को अपडेट करने का प्रवाह क्या है? ऐसा लगता है कि एक त्रुटि कॉलबैक को मॉडल को isError स्थिति में रखना चाहिए, और फिर दृश्य उचित संदेश प्रदर्शित कर सकता है। इसके अलावा, लेनदेन गंदे रहना चाहिए। इस तरह, लेनदेन rollback का उपयोग कर सकते हैं।

ऐसा लगता है कि store.recordWasInvalid का उपयोग सही दिशा में जा रहा है।

+4

त्रुटियों को संभालने के लिए अभी तक एक पूर्ण तंत्र नहीं है, https://github.com/emberjs/data/pull/376/ देखें, शायद आपको वह चाहिए जो आप चाहते हैं। –

+0

हां, त्रुटि प्रबंधन की कमी आश्चर्यजनक है, लेकिन यह अच्छा है कि निष्पक्ष कार्यान्वयन के विपरीत कोई त्रुटि प्रबंधन नहीं है जो बाद में बदल जाएगा। मैंने 'App.store.commit()' करने से पहले क्लाइंट-साइड पर कुछ मान्यताओं को निष्पादित करके सर्वर त्रुटियों से बचने के लिए अपना हालिया एम्बर ऐप लिखा है। – Mars

उत्तर

8

DS.RESTAdapter को this commit में थोड़ा और अधिक त्रुटि प्रबंधन मिला है, लेकिन हम अभी भी ऐसे बिंदु पर नहीं हैं जहां हमारे पास त्रुटि प्रबंधन के लिए एक बड़ी अनुशंसा है।

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

उम्मीद है कि हम आने वाले महीनों में इस प्रश्न को एक बेहतर उत्तर के साथ अपडेट कर सकते हैं।

+0

आज Ember.Data में त्रुटि प्रबंधन की स्थिति क्या है? –

2

चूंकि स्टॉक एम्बर-डेटा में वर्तमान में कोई अच्छा समाधान नहीं है, इसलिए मैंने apiErrors संपत्ति को DS.Model में जोड़कर और फिर मेरे RestAdapter subclass (मुझे पहले से ही अपनी आवश्यकता है) जोड़कर अपना स्वयं का समाधान बनाया है, मैंने अजाक्स में त्रुटि कॉलबैक जोड़ा createRecord और updateRecord के लिए कॉल करें जो त्रुटियों को सहेजते हैं और मॉडल को "अमान्य" स्थिति में डालते हैं, जिसका अर्थ क्लाइंट-साइड या सर्वर-साइड सत्यापन विफल होना चाहिए।

यह application.js या कुछ अन्य उच्च-स्तरीय फ़ाइल में जा सकते हैं:

DS.Model.reopen({ 
    // Added for better error handling on create/update 
    apiErrors: null 
}); 

यह createRecord और एक RestAdapter उपवर्ग में updateRecord के लिए त्रुटि कॉलबैक में चला जाता है

यहाँ कोड के टुकड़े है:

error: function(xhr, textStatus, err) { 
    console.log(xhr.responseText); 
    errors = null; 
    try { 
     errors = JSON.parse(xhr.responseText).errors; 
    } catch(e){} //ignore parse error 
    if(errors) { 
     record.set('apiErrors',errors); 
    } 
    record.send('becameInvalid'); 
} 
42

इस सप्ताह के अंत में मैं एक ही चीज़ को समझने की कोशिश कर रहा था। ल्यूक ने जो कहा, उसे छोड़कर, मैंने latest commit (11 दिसंबर) के लिए एम्बर-डेटा स्रोत पर नज़र डाली।

टीएलडीआर; एम्बर-डेटा अपडेट/त्रुटियों को बनाने के लिए, बस becameError() और becameInvalid(errors) को अपने DS.Model उदाहरण पर परिभाषित करें। RESTadapter के AJAX त्रुटि कॉलबैक द्वारा ट्रिगर किए गए कैस्केड अंततः इन कार्यों को परिभाषित करेंगे जिन्हें आप परिभाषित करते हैं।

उदाहरण:

App.Post = DS.Model.extend 
    title: DS.attr "string" 
    body: DS.attr "string" 

    becameError: -> 
    # handle error case here 
    alert 'there was an error!' 

    becameInvalid: (errors) -> 
    # record was invalid 
    alert "Record was invalid because: #{errors}" 

यहाँ स्रोत के माध्यम से पूर्ण की पैदल दूरी पर है:

बाकी अनुकूलक में, AJAX कॉलबैक त्रुटि फ़ंक्शन here दिया जाता है:

this.ajax(this.buildURL(root, id), "PUT", { 
     data: data, 
     context: this, 
     success: function(json) { 
     Ember.run(this, function(){ 
      this.didUpdateRecord(store, type, record, json); 
     }); 
     }, 
     error: function(xhr) { 
     this.didError(store, type, record, xhr); 
     } 
    }); 

didError परिभाषित किया गया है here और बदले में यह स्टोर के रिकॉर्ड को कॉल करता है WasInvalid या RecordWasError प्रतिक्रिया के आधार पर:

didError: function(store, type, record, xhr) { 
    if (xhr.status === 422) { 
     var data = JSON.parse(xhr.responseText); 
     store.recordWasInvalid(record, data['errors']); 
    } else { 
     store.recordWasError(record); 
    } 
    }, 

बारी में, store.recordWasInvalid और store.recordWasError (परिभाषित here) रिकॉर्ड कॉल (एक DS.Model) के संचालकों। अमान्य मामले में, यह एडाप्टर से त्रुटि संदेशों के साथ एक तर्क के रूप में गुजरता है।

recordWasInvalid: function(record, errors) { 
    record.adapterDidInvalidate(errors); 
    }, 

    recordWasError: function(record) { 
    record.adapterDidError(); 
    }, 

DS.Model.adapterDidInvalidate और adapterDidError (परिभाषित here) बस send('becameInvalid', errors) या send('becameError') जो अंत में संचालकों here करने के लिए हमें ले जाता है:

didLoad: Ember.K, 
    didUpdate: Ember.K, 
    didCreate: Ember.K, 
    didDelete: Ember.K, 
    becameInvalid: Ember.K, 
    becameError: Ember.K, 

(Ember.K this लौटने के लिए बस एक डमी समारोह है here देखें।)

तो, निष्कर्ष यह है कि आपकोके लिए फ़ंक्शंस को परिभाषित करने की आवश्यकता है इन मामलों को संभालने के लिए आपके मॉडल पर 0 और becameError

उम्मीद है कि यह किसी और की मदद करेगा; दस्तावेज़ निश्चित रूप से अभी इस पर प्रतिबिंबित नहीं करते हैं।

+2

यदि आप लेनदेन करने से पहले 'model.one (' BecInvalid ', फ़ंक्शन() {// त्रुटि प्रबंधन यहां}} जोड़कर आप एक ऑनटाइम कॉलबैक का उपयोग भी कर सकते हैं, यदि आप संदर्भ के आधार पर त्रुटियों को अलग-अलग संभालना चाहते हैं। –

+1

यह नष्ट करने के लिए काम नहीं करता है। क्या वो सही है? – RyanJM

+0

महान स्पष्टीकरण! बहुत बहुत धन्यवाद। – incognick

3

मैं बस ऐसी स्थिति में भाग गया, यह सुनिश्चित नहीं है कि यह पहले से कहीं भी समझाया गया है या नहीं।

मैं उपयोग कर रहा हूँ:

Em.VERSION : 1.0.0 
DS.VERSION : "1.0.0-beta.6" 
Ember Validations (dockyard) : Version: 1.0.0.beta.1 
Ember I18n 

मॉडल शुरू में मान्यता mixin साथ mixedin किया गया था।

App.Order = DS.Model.extend(Ember.Validations.Mixin, { 
..... 
someAttribute : DS.attr('string'), 
/* Client side input validation with ember-validations */ 
validations : { 
    someAttribute : { 
     presence : { 
      message : Ember.I18n.t('translations.someAttributeInputError') 
     } 
    } 
} 
}); 

टेम्पलेट में, संबंधित हैंडलबार जोड़े गए हैं। अब

<p>{{t 'translations.myString'}}<br> 
    {{view Ember.TextField valueBinding="attributeName"}} 
    {{#if model.errors.attributeName.length}}<small class="error">{{model.errors.attributeName}}</small>{{/if}} 
</p 

(ध्यान दें कि एंबर सत्यापन स्वचालित रूप से इनपुट सत्यापन के मामले में model.errors.<attribute> करने के लिए त्रुटियों जोड़ देगा, मैं सर्वर सत्यापन में एक ही व्यापार बंद के रूप में अच्छी तरह से उपयोग किया जाएगा), हम Order

App.get('order').save().then(function() { 
    //move to next state? 
}, function(xhr){ 
    var errors = xhr.responseJSON.errors; 
    for(var error in errors){ //this loop is for I18n 
    errors[error] = Ember.I18n.t(errors[error]); 
    } 
    controller.get('model').set('errors', errors); //this will overwrite current errors if any 
}); 
बचत हो जाएगा

अब अगर वहाँ कुछ मान्यता सर्वर से फेंक दिया त्रुटि है, तो वापस आ पैकेट इस्तेमाल किया जा रहा

{"errors":{"attributeName1":"translations.attributeNameEror", 
"another":"translations.anotherError"}} 

status : 422 

यह स्थिति उपयोग करने के लिए महत्वपूर्ण है

तो इस तरह, आपकी विशेषता को सर्वर पक्ष पर क्लाइंट पक्ष और फिर सत्यापित किया जा सकता है।

अस्वीकरण: मुझे यकीन नहीं है कि यह सबसे अच्छा तरीका है या नहीं!