Flutter: runZonedGuarded เอาไว้ทำอะไรนะ?

Published on

Authored by Pete. Pittawat Taveekitworachai.


เมื่อเราพัฒนาโปรแกรมขึ้นมานั้น ไม่ว่าจะในภาษาใดก็ตาม ข้อผิดพลาด (Error) เป็นสิ่งที่เราไม่อาจหลีกเลี่ยงได้ (Inevitable) แม้ว่าเราจะมั่นใจว่าเรานั้นพัฒนาโปรแกรมมาได้ดีเพียงใดก็ตาม ดังนั้นการแก้ไขข้อผิดพลาดของโปรแกรม (Debugging) จึงอาจถือได้ว่าเป็นหนึ่งในขั้นตอนที่มีความสำคัญอีกส่วนหนึ่งในการพัฒนาโปรแกรม

อย่างไรก็ตามแม้ว่าเราจะตั้งใจพัฒนาให้ดีแค่ไหนก็ตาม แต่ไม่มีอะไรที่สมบูรณ์แบบ ในสภาพแวดล้อมการทำงานแบบนักพัฒนานั้นเรายังสามารถติดตามและแก้ไขข้อผิดพลาดต่าง ๆ ได้อย่างง่ายดาย แต่หากเป็นข้อผิดพลาหลังจากที่เราทำการปล่อยแอปพลิเคชันของเราไปให้ผู้ใช้ได้ใช้งานเรียบร้อยแล้ว นั่นก็ทำให้เป็นเรื่องยากขึ้นที่จะติดตาม

เราจึงต้องอาศัยการเชื่อมต่อกับบริการเฝ้าระวังและติดตามข้อผิดพลาด (Error Monitoring and Tracking Service) เช่น Firebase Crashlytics, Sentry ในการส่งต่อข้อผิดพลาดต่าง ๆ พร้อมข้อมูลเพิ่มเติม เพื่อช่วยให้เราวิเคราะห์ได้ง่ายขึ้น

อย่างไรก็ตามบางครั้งเราก็อาจจะใช้บริการเหล่านี้หลากหลายตัว เพื่อแยกประเภทของข้อผิดพลาดต่าง ๆ ออกจากกัน เช่น ข้อผิดพลดาที่เกิดจาก API ภายนอกที่แอปของเราเชื่อมโยงอยู่ หรือข้อผิดพลาดที่เกิดขึ้นจากแอปพลิเคชันของเราเอง

เราอาจจะสามารถเขียน If-else มาดักการทำงานต่าง ๆ เห่านี้ได้ แต่จะดีกว่ามั้ยถ้ามีฟังก์ชันที่สวยงามและพร้อมให้เราใช้งานได้เลย

ใน Flutter หากเราต้องการจัดการตามเหตุการณ์ดังกล่าวกับ Future เรามีสิ่งที่เรียกว่า runZoned() อย่างไรก็ตามในบทความนี้จะพูดถึง runZonedGuarded() เลย เนื่องจาก runZoned() นั้นถูกประกาศให้เลิกใช้งาน (Deprecated) ตั้งแต่ Dart 2.8 เป็นต้นมา

Syntax ของ runZonedGuarded() นั้นจะเป็นดังนี้

    runZonedGuarded(futureTask(), errorHandler());

runZonedGuarded() นั้นเราสามารถนำไปครอบการทำงานที่มีการคืนค่าที่เป็น Future หรืองานที่เป็น Asynchronus Task ต่าง ๆ ได้ โดยมีการส่งข้อมูลนำเข้าเพิ่มเติมไปให้ runZonedGuarded() อีกหนึ่งตัวนั่นคือฟังก์ชันสำหรับการรับมือกับข้อผิดพลาด (Error Handler) โดยฟังก์ชันนี้นั้นสามารถใช้ทดแทน .catchError() ตามปกติได้เลย และ runZonedGuarded() จะส่งของมาให้สองอย่างนั่นคือ Map ที่โดยปกติมักจะเป็น Error ที่เกิดขึ้น และ ZoneSpecification ซึ่งเป็น Object ที่มีการเก็บข้อมูลเพิ่มเติมเกี่ยวกับ Zone ไว้ และอนุญาตให้เราสามารถปรับแต่งค่าบางอย่างให้กับ Zone ได้

ตัวอย่างเช่น

    runZonedGuarded(() {
    	Future(() {
    		throw "asynchronous error";
    	});
    }, 
    (e, s) => print(e)
    );

จากตัวอย่างโค้ด จะเห็นได้ว่าเรานำ runZonedGuarded() ไปครอบให้กับ Future ซึ่งทำอย่างเดียว นั่นคือการ throw ข้อผิดพลาดออกมา ซึ่งหลังจากที่เกิดข้อผิดพลาด ขึ้นแล้วแทนที่จะลอยขึ้นไปตามลำดับชั้น จนอาจส่งผลให้แอปพลิเคชันของเราหยุดการทำงานนั้น ก็จะเข้าไปที่ Error Handler แทน ซึ่งภายใน Error Handler นั้น เราก็เขียนให้แสดงผลลัพธ์ของข้อผิดพลาดนั้นออกมา

ตรงจุดนี้เองแทนที่เราจะแสดงผลลัพธ์ออกมา เราสามารถประยุกต์ใช้ด้วยการส่งต่อให้กับบริการติดตามข้อผิดพลดาดังที่กล่าวไปข้างต้น โดยเราอาจจะเพิ่มเติมข้อมูลต่าง ๆ เข้าไปด้วยก็ได้เช่นกัน

การประยุกต์ใช้อื่น ๆ สำหรับ runZonedGuarded() ก็อาจเป็นการที่เราต้องการแยกบางส่วนของโปรแกรมออกมา ไม่ให้ข้อผิดพลาดที่เกิดขึ้นจากส่วนนั้น ๆ ไปยุ่งเกี่ยวกับส่วนอื่น ๆ นั่นเอง

สำหรับคนที่สนใจศึกษาเพิ่มเติม สามารถอ่านได้ที่ Flutter API Reference


📚 Hope you enjoy reading! 📚