أنغولار - لا تغلق Observable بعد حدوث خطأ
أعلم أن هذا السؤال قد يبدو بسيطًا جدًا، لكن المصادر على الإنترنت حول القابليات للرصد والتعامل مع الأخطاء ليست جيدة جدًا (أو ربما أنا سيء في البحث فقط).
لدي طلب http يُرجع Observable من Response، هذه الاستجابات يمكن أن تحتوي إما على بيانات أو رسالة خطأ. إذا كانت تحتوي على بيانات أريد استخراجها وتحليلها، وإذا كانت تحتوي على رسالة خطأ أريد تخطي جميع العمليات الأخرى (حول التحليل) وتنفيذ دالة الخطأ في المشترك.
يمكنني القيام بكل هذه الأشياء مع رمي خطأ:
http.get(...).
...
.do(res=>{
if(res.error) throw new Error(res.error.message);
return res;
})
ويعمل، فهو يتجاوز جميع العاملين وينفذ دالة الخطأ. المشكلة هي أنه، بعد الخطأ، يتوقف المشترك ولا يقبل البيانات بعد الآن.
إذا قمت بتحليل المشترك بعد الخطأ، ألاحظ أن الخاصيتين closed و isStopped تم ضبطهما على true كلاهما. أريد منع هذا، أريد الحفاظ على المراقب نشطًا أيضًا بعد الأخطاء. كيف يمكنني فعل ذلك؟
شكراً
الإجابة رقم 1
كما ذُكر في الإجابات السابقة، هذا هو السلوك القياسي، المكفول بعقد Rxjs الخاص بالملاحظات. إذا كنت ترغب في الهروب من العقود، يمكنك materialize المصدر الخاص بك، وفي هذه الحالة، بدلاً من التعامل مع الرسائل المتدفقة من خلال ملاحظتك، ستتعامل مع الرسائل الوصفية (تسمى الإشعارات، من الأنواع الثلاثة التي تتوقعها، next، error، complete). لا يوجد عقد على الرسائل الوصفية، مما يضع العبء عليك لإنشاء رسائل الخطأ والإكمال يدويًا، أو استخدام dematerialize للعودة إلى السلوك الطبيعي.
بشكل عام، الملاحظات رائعة لتدفق البيانات، بينما يكون تدفق التحكم عادةً مرهقًا (القفز، التكرار، التشعب الشرطي، إلخ).
راجع توثيق Notification هنا: http://reactivex.io/rxjs/class/es6/Notification.js~Notification.html.
راجع توثيق materialize هنا: http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-materialize
لذلك إذا كنت تريد التعامل مع الأخطاء دون إيقاف المصدر القابل للملاحظة الخاص بك، يمكنك فعل شيء مثل هذا:
function process(source, success, error) {
return source.materialize()
.map(function(notification){
const value = notification.value; // that is the actual message data
if (notification.kind === 'N') {
// that is a next message, we keep it a next message
return Notification.createNext(success(value));
}
if (notification.kind === 'E') {
// that is a error message, we turned into a next message
return Notification.createNext(error(value));
}
if (notification.kind === 'C') {
// that is a completed message, we keep it a completed message
return Notification.createComplete();
}
})
.dematerialize()
}
يمكنك بعد ذلك استخدام هذه الدالة مع المصدر القابل للملاحظة الخاص بك وتمرير دالتي النجاح والخطأ التي تعالج القيمة المتدفقة. كما ترى، التقنية هنا هي تحويل رسالة الخطأ إلى رسالة عادية، ثم العودة إلى الوضع الطبيعي.
تم فعل هذا من خلف رأسي لذلك هو غير مختبر، لذا أبقوني على اطلاع إذا كان ذلك مفيدًا لكم. لقد استخدمت تقنية مشابهة عدة مرات مع Rxjs v4، وأعتقد أنه يجب أن تُترجم إلى Rxjs v5 بطريقة مباشرة.
الإجابة رقم 2
ما تطلبه ينكسر حرفيًا عقد الـ Observable. يُعرف الـ Observable على أنه منتج لقيم 0 أو أكثر، وإذا أنهى المنتج إنتاج القيم، فسيستدعي معالج complete على المراقب الخاص به، وإذا كان هناك خطأ، فسيستدعي error.
ولكن بمجرد أن يستدعي complete أو error، فإن عقده هو أنه لن يستدعي next على المتابع الخاص به مرة أخرى.
هناك طرق لتجاوز هذا - من خلال تأليف الملاحظات الخاصة بك بشكل صحيح، يمكنك استئناف تدفقك بملاحظة جديدة. لكن بدون سياق إضافي، من الصعب إرشادك أكثر. الفكرة الأساسية تدور حول استخدام عامل .catch في سلسلة الملاحظات الخاصة بك لإنشاء ملاحظة جديدة عند حدوث خطأ، لكن مرة أخرى، سيكون هناك حاجة إلى سياق إضافي لتقديم مثال.
تعديل:
كما أضاف @cartant بشكل مفيد، انظر العقد القابل للملاحظة
