Masoud-Dev
Masoud-Dev
خواندن ۴ دقیقه·۲ سال پیش

Dio Interceptors

Interceptors tree
Interceptors tree


گاهی اوقات برنامه‌ها خیلی ساده هستند مثلا یه درخواستی رو میفرستیم به یه سروری و یه لیست بهمون برمیگردونه، مثل:

Future<Response> fetchItems() { return Dio().(&quothttps://some-website.com/listing&quot); }

هندل کردن اروری نداریم، نیازی نیست که ریسپانس‌هایی که داریمو لاگ بندازیم و هیچ catch کردنی وجود نداره!

ولی همیشه برنامه‌ها اینقد ساده نیستند، و بعضی اوقات کارهای بیشتری نیاز هست که انجام بدیم تا ریسپانس مناسب رو از سرور بگیریم یا بخوایم برناممون رو دیباگ کنیم، حالا این کارهای بیشتری که میگیم چیا هستن:

  • ارسال کردن یه هدر داینامیک به سرور. برای مثال وقتی میخوایم یه کلیدی که داخل shared preference ذخیره شده رو ارسال کنیم.
  • یا اگه بخوایم مقادیری که از ریسپانس سرور می‌گیریم بخوایم یه جایی بصورت لوکال ذخیرش کنیم.
  • یا ارورهایی که از سمت سرور برامون ارسال میشه رو بخوایم بدیم به کلاس مربوطش تا برنامه اونو هندل کنه.
  • علاوه بر این، ممکنه بخوایم یه cache ساده به برناممون اضافه کنیم مثلا وقتی کانکشن تایم آوت گرفتیم یا کاربر اینترنت نداشت، ما میتونیم ریسپانس قبلی سرور رو بهش بدیم.
  • و در آخر برحسب نیاز ممکنه بخوایم همه‌ی ریسپانس‌ها و درخواست‌ها رو لاگ بگیریم.

اینجاست که آقای Interceptors که داخل پکیج Dio هست وارد عمل میشه و به ما تو هندل کردن این موارد با کال بک‌های خاصش (errors، requests و response) کمک میکنه. معنی لغوی این کلمه میشه «حائل شدن» در اینجا بین سرور و یوزر قرار میگیره و قبل اینکه درخواست توسط سرور هندل بشه یه صحت سنجی در قسمت خود یوزر انجام میشه.

قبل اینکه بریم وارد مبحث اینکه چطور میشه از interceptors استفاده کرد بشیم اجازه بدید یه قدم بریم عقب و ببینیم Dio چطور میتونه config بشه:

Dio createDio() { return Dio( BaseOptions( connectTimeout: 5000, receiveTimeout: 5000, baseUrl: &quothttps://some-website.com&quot ) ); }

به هر حال، یه چیزی که نمیتونم به این کانفیگ اضافه کنیم (در این لحظه که دارم این مقاله رو مینویسم) اون Interceptors هست.

برای استفاده از Interceptors می‌تونیم به دو روش عمل کنیم:
- ساخت یک شی از Dio یا built-in
- ساخت کاستوم کلاس و extends کردن از Interceptors

Interceptors tree
Interceptors tree


نکته: با interceptors ما میتونیم درخواستهارو قبل اینکه توسط سرور هندل بشند پردازش کنیم.

روش اول (ساخت یک شی از Dio یا روش built-in):

Dio addInterceptors(Dio dio) { return dio ..interceptors.add( InterceptorsWrapper( onRequest: (options, handler) => requestInterceptor(options, handler), onResponse: (response, handler) => responseInterceptor(response, handler), : (dioError, handler) => errorInterceptor(dioError, handler), ), ); }

و با این حرکت ما یه شی کانفیگ شده از Dio داریم که میتونیم برای هر APIی که میسازیم ازش استفاده کنیم.

در توضیح کد بالا بگم که ما یک شی از Dio ساختیم به نام addInterceptors که یه پارامتر از نوع Dio میگیره.

همونطور که در اول مقاله گفتیم، بیایید فرض کنیم که یه header داریم که یه مقدار ذخیره شده داخل shared preferences داخلش فراخوانی شده (خب ما یه مقدار داینامیک داخلش گذاشتیم و هر لحظه ممکنه یه مقدار داشته باشه) و تابع DateTime.now که باز هم یه مقدار متغیره.

نکته: از اونجا که مقادیر داینامیکی داریم نمی‌تونیم از فیلد extra که BaseOptions داره استفاده کنیم.

خب اینجاست که InterceptorWrapper به ما یه شی از RequestOptions میده که پراپرتی‌هایی داره مثل:
- dynamic data
- String path
- Map<String, dynamic> queryParameters

با این اطلاعات میتونیم متد requestInterceptor خودمونو پیاده کنیم.

این متد یه مقدار داینامیکی رو برگردونه که میتونه از انواع زیر باشه:
- میتونه از نوع RequestOptions باشه اگه میخوایم با همین request ادامه بدیم.
- یا میتونه از نوع Response باشه اگه بخوایم خود اپ به request رسیدگی کنه.
- یا میتونه DioError یا dio.reject باشه اگه بخوایم یه اروری بفرستیم.

این به ما قابلیت validate هر ریکوئستی رو میده قبل اینکه ساخته بشه یا بخوایم add data کنیم و یا اروری throw بشه.

توضیحات داکیومنت خود Dio در مورد Interceptors:

برای هر شی dio، ما می‌تونیم یک یا چند Interceptors اضافه کنیم، با هر کدوم میتونیم Intercept کنیم requests, response & errors قبل اینکه تو then یا catchError هندل بشند.

InterceptorsWrapper
InterceptorsWrapper


خب بریم سراغ متد onRequest که برای ارسال درخواست به سرور هست و به ما اجازه میده قبل ارسال به سرور یک سری تغییرات بدیم و بعد به سرور ارسال کنیم.
- handler.next(option) میگه هیچ تغییری نده پاسش بده مرحله بعد
- handler.resolve(response) اگه بخوایم یسری کاستوم دیتا به ریکوئست/ریسپانس خودمون اضافه کنیم
- handler.reject(dioError) اگه بخوایم درخواست رو قبل ارسال شدن با یه ارور مسیجی reject کنیم

متد بعدی onResponse هستش که اگه بخوایم با جواب برگشتی (response) یه کارایی بکنیم:
- handler.next(response) میگه هیچ تغییری نده پاسش بده مرحله بعد
- handler.reject(dioError) اگه بخوایم درخواست رو قبل ارسال شدن با یه ارور مسیجی reject کنیم

متد بعدی که جوابهایی که از سمت سرور میاد رو اگه ارور داشته باشه تو این متد هندل میکنیم:
- handler.next(e) میگه هیچ تغییری نده پاسش بده مرحله بعد
- handler.resolve(response) اگه به مشکلی خوردیم اینجا میشه حللش کرد

CustomInterceptor class extends Interceptor
CustomInterceptor class extends Interceptor


بریم یه نمونه resolve کردن رو با هم ببینیم:

handler.resolve
handler.resolve


امیدوارم استفاده لازم رو از این آموزش برده باشید.
با لایک و کامنت انگیزه بدید دوباره آموزشی بزارم :)
دوستدار شما مسعود سعیدی





شاید از این پست‌ها خوشتان بیاید