मैंने कुछ पोस्ट पढ़ी हैं जो कहती हैं कि RxSwift से निपटने का सबसे अच्छा अभ्यास केवल ऑनरर को घातक त्रुटि देना और परिणाम को ऑननेक्स्ट में पास करना है।

यह मेरे लिए तब तक समझ में आता है जब तक मुझे एहसास नहीं होता कि मैं अब पुनः प्रयास नहीं कर सकता क्योंकि यह केवल त्रुटि पर होता है।

मैं इस मुद्दे से कैसे निपटूं?

एक और सवाल यह है कि मैं वैश्विक और स्थानीय पुनर्प्रयास मिश्रणों को एक साथ कैसे संभालूं?

एक उदाहरण होगा, iOS रसीद सत्यापन प्रवाह।

1, स्थानीय रूप से रसीद प्राप्त करने का प्रयास करें

2, विफल होने पर, नवीनतम रसीद के लिए Apple सर्वर से पूछें।

3, पुष्टि करने के लिए हमारे बैकएंड को रसीद भेजें।

4, यदि सफलता मिलती है, तो संपूर्ण प्रवाह पूर्ण

5, यदि विफल हो, तो त्रुटि कोड की जाँच करें यदि यह पुन: प्रयास करने योग्य है, तो 1 पर वापस जाएँ।

और नए 1 में, यह ऐप्पल सर्वर से नई रसीद मांगने के लिए बाध्य होगा। फिर जब यह फिर से 5 पर पहुंच जाता है, तो पूरा प्रवाह रुक जाएगा क्योंकि यह पहले से ही दूसरा प्रयास है। अर्थ केवल एक बार पुनः प्रयास करें।

तो इस उदाहरण में, यदि राज्य मशीन का उपयोग कर रहे हैं और rx का उपयोग किए बिना, मैं राज्य मशीन का उपयोग कर रहा हूं और कुछ वैश्विक स्थिति साझा करता हूं जैसे isSecondAttempt: Bool, shouldForceFetchReceipt: Bool, आदि।

मैं इस प्रवाह को rx में कैसे डिज़ाइन करूं? प्रवाह में डिज़ाइन किए गए इन वैश्विक साझा राज्य के साथ।

5
Tony Lin 19 फरवरी 2019, 12:35

1 उत्तर

सबसे बढ़िया उत्तर

मैंने कुछ पोस्ट पढ़ी हैं जो कहती हैं कि RxSwift से निपटने का सबसे अच्छा अभ्यास केवल ऑनरर को घातक त्रुटि देना और परिणाम को ऑननेक्स्ट में पास करना है।

मैं उस भावना से सहमत नहीं हूं। यह मूल रूप से कह रहा है कि यदि प्रोग्रामर ने गलती की है तो आपको केवल onError का उपयोग करना चाहिए। आपको अन-हैप्पी पथों के लिए या किसी प्रक्रिया को निरस्त करने के लिए त्रुटियों का उपयोग करना चाहिए। वे एक एसिंक तरीके से छोड़कर फेंकने की तरह हैं।

आरएक्स श्रृंखला के रूप में आपका एल्गोरिदम यहां दिया गया है।

enum ReceiptError: Error {
    case noReceipt
    case tooManyAttempts
}

struct Response { 
    // the server response info
}

func getReceiptResonse() -> Observable<Response> {
    return fetchReceiptLocally()
        .catchError { _ in askAppleForReceipt() }
        .flatMapLatest { data in
            sendReceiptToServer(data)
        }
        .retryWhen { error in
            error
                .scan(0) { attempts, error in
                    let max = 1
                    guard attempts < max else { throw ReceiptError.tooManyAttempts }
                    guard isRetryable(error) else { throw error }
                    return attempts + 1
                }
        }
}

यहां वे समर्थन कार्य दिए गए हैं जिनका उपयोग ऊपर किया गया है:

func fetchReceiptLocally() -> Observable<Data> {
    // return the local receipt data or call `onError`
}

func sendReceiptToServer(_ data: Data) -> Observable<Response> {
    // send the receipt data or `onError` if the server failed to receive or process it correctly.
}

func isRetryable(_ error: Error) -> Bool {
    // is this error the kind that can be retried?
}

func askAppleForReceipt() -> Observable<Data> {
    return Observable.just(Bundle.main.appStoreReceiptURL)
        .map { (url) -> URL in
            guard let url = url else { throw ReceiptError.noReceipt }
            return url
        }
        .observeOn(ConcurrentDispatchQueueScheduler(qos: .userInitiated))
        .map { try Data(contentsOf: $0) }
}
4
Daniel T. 19 फरवरी 2019, 13:17