การใช้งาน Asynchronous Programming ในภาษา Dart เบื้องต้น

เขียนเมื่อ 4 ปีก่อน โดย Ninenik Narkdee
dart async await future class asynchronous

คำสั่ง การ กำหนด รูปแบบ ตัวอย่าง เทคนิค ลูกเล่น การประยุกต์ การใช้งาน เกี่ยวกับ dart async await future class asynchronous

ดูแล้ว 9,993 ครั้ง


เนื้อหาตอนต่อไปนี้ เราจะมาดูเกี่ยวกับการทำงานในรูปแบบ Asynchronous
และทำความรู้จักกับการใช้งาน Futore class รวมถึง การใช้งาน "async" 
และ "await" keyword
 
สามารถทดสอบการเขียนโปรแกรมผ่านเว็บไซต์ DartPad
 
 

ทำไมการใช้งาน Asynchronous จึงเป็นสิ่งจำเป็น

    การทำงานในรูปแบบ Asynchronous ช่วยให้โปรแกรมของเราสามารถทำงานต่อเนื่องอย่างสมบูรณ์ได้ ในขณะที่ยังมีการดำเนินการ
อื่นอยู่ ยกตัวอย่างเช่น การเรียกดูข้อมูลผ่านเครือข่ายเน็ตเวิร์ค  การบันทึกข้อมูลลงฐานข้อมูล  การอ่านข้อมูลจากไฟล์ เป็นต้น
 
    สำหรับการใช้งาน asynchronous ใน Dart  เราสามารถใช้ Future class ในการจัดการ ร่วมกับคีร์เวิร์ด async และ await
    มาดูตัวอย่างเล็กน้อย ของรูปแบบการทำงานแบบ asynchronous ที่ไม่ถูกต้อง
 
void main () {
  // เมื่อมีการเรียกใช้ฟังก์ชั่น createOrderMessage()
  print(createOrderMessage());
  // ผลลัพธ์ที่ได้ จะเป็น แสดงข้อความว่า 
  // Your order is: Instance of '_Future<String>'
}
// ฟังก์ชั่น่สำหรับจำลองแสดงข้อมูลการสั่งซื้อ
String createOrderMessage () {
  var order = getUserOrder();  // เรียกข้อมูลการสั่งซื้อจากฟังก์ชั่น getUserOrder() อีกที
  return 'Your order is: $order'; // คืนค่าข้อมูลการสั่งซื้อ
}
 
// ฟังก์ชั่นจำลอง ข้อมูลการสั่งซื้อ
Future<String> getUserOrder() {
  // จำลอง และสมมติว่า การทำงานส่่วนนี้มีความซับซ้อน และทำงานช้า
  // โดยให้ดีเลย์การคืนค่ากลับในอีก 4 วินาที
  return Future.delayed(Duration(seconds: 4), () => 'Large Latte'); 
}
 
    จะเห็นเมื่อเราเรียกฟังก์ชั่น createOrderMessage() ตัวแปร order จะมีการกำหนดค่าให้มีค่าเท่ากับ ค่าที่ได้จากการเรียก
ใช้งานฟังก์ชั่น getUserOrder() อีกที  และค่าที่คืนมาจากฟังก์ชั่นนี้ จะใช้เวลา 4 วินาที ถึงจะคืนค่ากลับมา เป็นลักษณะของการ
ทำงานแบบ asynchronous  แต่เนื่องจาก เราไม่ได้กำหนดรูปแบบของข้อมูล ว่าเป็นแบบ asynchronous ทำให้ในบรรทัดต่อมา
มีการคืนค่าในทันที โดยที่ยังไม่ถึง 4 วินาที จากคำสั่ง 
 
return 'Your order is: $order'; // คืนค่าข้อมูลการสั่งซื้อ
    ทำให้ผลลัพธ์ของต้วแปร order ซึ่งเราใช้ $order สำหรับแสดงในรูปแบบข้อความ มีค่าเป็น 
 
// Your order is: Instance of '_Future<String>'
    แทนที่จะเป็น // Your order is: Large Latte
 
    สามารถสรุปลักษณะการทำงานของรูปแบบข้างต้น ได้ดังนี้ ว่าทำไมผลลัพธ์ที่ได้ จึงไม่เป็นค่าผลลัพธ์สุดท้ายที่คำสั่ง getUserOrder() 
ส่งกลับออกมา ทำไมจึงเป็น ข้อความที่บอกแค่เพียงว่าเป็น instance ของ Future 
    - คำสั่ง getUserOrder() เป็น asynchronous ฟังก์ชั่น ที่มีเรื่องของเวลาที่ต้องรอ เข้ามาเกี่ยวข้อง ทำให้ข้อความสุดท้ายของผลลัพธ์
      ที่เป็นข้อความว่า "Large Latte" มีการ delay หรือต้องรอเป็นเวลา 4 วินาที ก่อนที่จะถูกส่งกลับออกมา
    - ในการเรียกดูข้อมูลการสั่งซื้อด้วยคำสั่ง createOrderMessage() ที่จะมีเรียกใช้คำสั่ง getUserOrder() ด้านในอีกที และรอจนกว่าจะ
      สำเร็จเสร็จสิ้น  แต่ด้วยว่า คำสั่ง createOrderMessage() เป็นแบบ synchronous ฟังก์ชั่น จึงไม่ได้มีการรอให้การทำงานของคำสั่ง
      getUserOrder() จบก่อน ทำให้ค่าที่ได้กลับมา จึงไม่ใช่ค่าผลลัพธ์สุดท้ายที่ถูกต้อง
    - กลายเป็นว่า คำสั่ง createOrderMessage() กลับได้ค่าที่แสดงถึง การทำงานที่ยังไม่เสร็จสิ้น ในที่นี้คือ instance ของ Future class
    - ดังนั้น ค่าที่ได้จึง เป็นข้อความว่า Instance of '_Future<String>' แทน
 
 
    ก่อนที่เราจะทำความรู้จักกับ futures, async และ await เพื่อนำมาใช้งานกับการทำงานในรูปแบบ asynchronous ข้างต้น มาทบทวน
คำเหล่านี้กัน
 
    การทำงานแบบ synchronous
        รูปแบบการทำงานที่เป็นไปอย่างต่อเนื่องตามลำดับ  โดยถ้าการทำงานในส่วนใด ยังไม่เสร็จเรียบร้อย ก็จะไม่มีการทำงานต่อในส่วนอื่น
    ต่อได้ จนกว่าตัวที่กำลังทำงานอยู่ เสร็จเรียบร้อยแล้วเท่านั้น เข้าใจอย่างง่าย เช่น ทำงานด้วยคำสั่งแรก ยังไม่เสร็จ ก็จะไม่มีการทำงานใน
    คำสั่งที่สอง หรือคำสั่งในลำดับถัดๆ ไปได้
 
    ฟังก์ชั่น synchronous
        เป็นฟังก์ชั่นที่ทำงานในรูปแบบการทำงานแบบ synchronous เท่านั้น
 
    การทำงานแบบ asynchronous
        รูปแบบการทำงานที่เมื่อถูกเรียกใช้งานแล้ว จะทำการรอผลลัพธ์ค่าสุดท้าย และในขณะเดียวกัน การทำงานของส่วนอื่น ก็ยังทำงานต่อเนื่อง
    ไปได้ แม้ส่วนแรกยังทำงานไม่เสร็จก็ตาม เข้าใจอย่างง่าย เช่น ทำงานด้วยคำสั่งแรก และในขณะที่คำสั่งแรกยังรอข้อมูลสุดท้ายอยู่ ก็สามารถ
    ทำงานในคำสั่งที่สองหรือคำสั่งในลำดับถัดๆ ไปได้  เป็นรูปแบบของการทำงานที่มีเรื่องของเวลาที่ต้องรอเข้ามาเกี่ยวข้อง
 
    ฟังก์ชั่น asynchronous
        เป็นฟังก์ชั่นที่ทำงานอยู่ในรูปแบบการทำงานแบบ asynchronous และสามารถใช้งานในรูปแบบการทำงาน synchronous อีกด้วย

 
 

Future ในภาษา Dart คืออะไร

    คำว่า "future" (ตัว f พิมพ์เล็ก) จะหมายถึง instance ของ "Future" (ตัว F พิมพ์ใหญ่)  เข้าใจอย่างง่ายก็คือ Object หนึ่งที่แสดงถึงผลลัพธ์
ที่ได้จากการทำงานในรูปแบบ asynchronous (อาจจะเข้าใจเป็นว่า ค่าที่จะได้มาหรือสิ่งที่จะเกิดขึ้นในอนาคตข้างหน้า ก็ได้)
    โดยค่าของ future จะมีด้วยกันสอง state ก็คือ uncompleted และ completed
    ในภาษา Dart คำว่า uncompleted ใน future state จะหมายถึง ค่าก่อนที่จะมีส่งค่าสุดท้ายกลับมามา หรือก็คือค่าขณะ pending (กำลังรอข้อมูล)
 
    เรามาทำความเข้าใจเพิ่มเติม กับค่าเหล่านี้กัน 
 
    Uncompleted
        เมื่อมีการเรียกใช้งาน asynchronous ฟังก์ชั่น ซึ่งมีเรื่องของเวลาที่ต้องรอเข้ามาเกี่ยวข้อง ค่า uncompleted future เป็นค่า future  ในกรณีที่กำลัง
    รอให้การทำงานของเสร็จสิ้นก่อน หรืออาจจะเป็นค่ากรณีที่เกิด error ก็ได้
 
    Completed
        เมือการทำงานในรูปแบบ asynchronous เสร็จสิ้นลง จะมีสองกรณีคือ กรณีที่สำเร็จพร้อมกับมีการส่งค่ากลับมา และกรณี error
        - กรณีสำเร็จพร้อมมีค่าส่งกลับมา เป็นข้อมูล Future<T> เมื่อ T คือชนิดข้อมูล เช่น Future<String> เป็นชนิดข้อมูลที่ถูกต้อง
          และสามารถนำไปใช้งานได้ แต่ถ้าเป็นชนิดข้อมูลที่ไม่ถูกต้องหรือไม่สามารถใช้งานได้ จะคืนค่ากลับมาเป็น Future<void> หรือก็คือ ไม่มี
          การคืนค่าใดๆ กลับมา ซึ่งก็คือค่า NULL 
        - กรณีสำเร็จแต่อาจจะเกิด errror ในเหตุผลใดๆ ก็ตาม
 
    ดูตัวอย่างการใช้งาน Future
 
void main () {
  // เรียกใช้งาน asynchronous ฟังก์ชั่น 
  getUserOrder();
  // ต่อด้วยทำคำสั่งลำดับถัดไป
  print('Fetching user order...');
}
// จำลองการทำงานของ asynchronous ฟังก์ชั่น 
Future<void> getUserOrder() {
  // สมมติว่ามีการไปดึงข้อมูลจาก database และต้องรอประมาณ 3 วินาทีที่ข้อมูลจะถูกส่งกลับมา
  return Future.delayed(Duration(seconds: 3), () => print('Large Latte'));
}
 
    รูปแบบการใช้งานข้างต้น จะเห็นว่า getUserOrder() เป็น asynchronous ฟังก์ชั่น ที่นำมาใช้งานใน  ฟังก์ชั่น main() ที่มีรูปแบบการใช้งานเป็น
แบบ synchronous ตามที่เราได้อธิบายไปด้านบนว่า ฟังก์ชั่น asynchronous สามารถใช้งานในรูปแบบการทำงาน synchronous ได้
    มาอธิบายต่อที่โค้ดตัวอย่างด้านบน ในตัวอย่าง คำสั่ง getUserOrder() จะคืนค่า future ที่ completed หลังจากที่ทำการ พิมพ์ข้อความออก
มาทาง console เนื่องจากรูปแบบการใช้งานที่เรากำหนดคือ ใช้เป็น Future<void> ที่ไม่มีการคืนค่าใดๆ กลับออกมา
    จากรูปแบบการใช้งาน ถึงแม้จะมีการเรียกใช้คำสั่้ง getUserOrder() ก่อนคำสั่ง print() แต่ค่าที่ได้จาก คำสั่ง getUserOrder() จะแสดงหลัง
จากข้อความ “Fetching user order…” เนื่องจากข้อความมีการ delay หรือก็คือมีเรื่องเวลาที่ต้องรอเข้ามาเกี่ยวข้อง  ถ้าพิจารณาดีๆ จะเห็นว่า
ถ้า getUserOrder() เป็นการทำงานแรก และ print() เป็นการทำงานที่สอง  ในขณะที่การทำงานแรกยังไม่เสร็จสิ้น การทำงานที่สอง ก็สามารถทำงาน
ต่อเนื่องได้ทันที เพราะการทำงานแรกเป็นรูปแบบการใช้งานแบบ asynchronous นั่นเอง
 
 
    เรามาดูอีกตัวอย่าง แต่เป็นกรณี error 
 
void main () {
  // เรียกใช้งาน asynchronous ฟังก์ชั่น 
  getUserOrder();
  // ต่อด้วยทำคำสั่งลำดับถัดไป
  print('Fetching user order...');
}
// จำลองการทำงานของ asynchronous ฟังก์ชั่น ที่ completed พร้อมกับ error
Future<void> getUserOrder() {
// สมมติไปดึงข้อมูลจาก database และต้องรอ 3 วินาที แล้วเกิด error ขึ้น
  return Future.delayed(Duration(seconds: 3), () => throw Exception('Logout failed: user ID is invalid'));
}
    ตัวอย่างข้างต้นคำสั่ง getUserOrder() ทำงานสำเร็จแต่มี error เกิดขึ้น โดยแจ้งว่า user ID ไม่ถูกต้อง
 
    ตอนนี้เราได้รู้จักการทำงานของ Future ในเบื้องต้นไปแล้ว ต่อไปเราจะมาดูวิธีการใช้งานค่าผลลัพธ์กรณี future คืนค่าผลลัพธ์เป็นข้อมูลกลับมา
 
 
 

การใช้งาน async และ await

    เมื่อไรก็ตามที่เราต้องการกำหนดฟังก์ชั่น asynchronous และ ใช้งานค่าผลลัพธ์ที่คืนกลับมา เราจะต้องมีการใช้งาน "async" และ "await" keyword
ร่วมอยู่ด้วย โดยรูปแบบการกำหนดสำหรับใช้งานเป็นดังนี้
 
    - ในการกำหนด async ฟังก์ชั่น ให้เราเพิ่ม "async" ไว้ก่อนส่วนของ body ของ ฟังก์ชั่น
    - ให้การเรียกใช้งาน async ฟังก์ชั่น เราต้องกำหนด "await" ไว้ด้านหน้าของ async ฟังก์ชั่นที่เรียกใช้งานเสมอ
    ตัวอย่างการเปลี่ยน main() จาก synchronous  เป็น asynchronous จะได้เป็น
 
void main() async {
  // code
}
    สังเกตโดยปกติแล้ว ฟังก์ชั่น main() จะมี return type เป็น void หรือก็คือไม่มีการคืนค่าใดๆ กลับมา ในกรณีไม่มีการกำหนด retun type ค่าเริ่มต้น
จะเป็น void   เช่นกัน สำหรับกรณีที่เป็น asynchronous หากไม่มีการกำหนด ก็จะเป็น Future<void> ซึ่งก็เท่ากับ void ดังนั้น ฟังก์ชั่น main() ข้างต้น
เราจะละไม่กำหนด return type หรือกำหนดเป็น void หรือจะกำหนดเป็น Future<void> ก็มีค่าเท่ากัน
 
// ไม่มีการคืนค่าใดๆ 
main()
void main()
void main() async
Future<void> main() async
    ต่อไปเราจะลองปรับโค้ดตอนต้นบทความ มาใช้งาน async และ await จะได้เป็นดังนี้
 
void main () async {
  // เมื่อมีการเรียกใช้ฟังก์ชั่น createOrderMessage() ในลักษณะที่ว่า เป็นฟังก์ชั่นที่ต้องรอ
  // โดยใช้ await กำหนดด้านหน้า
 print(await createOrderMessage());
  // ผลลัพธ์ที่ได้ จะเป็น แสดงข้อความว่า 
  // Your order is: Large Latte
}
// ฟังก์ชั่น่สำหรับจำลองแสดงข้อมูลการสั่งซื้อ แบบ Asynchronous
Future<String> createOrderMessage() async {
  // เรียกข้อมูลการสั่งซื้อจากฟังก์ชั่น getUserOrder()
  var order = await getUserOrder();   
  // ค่าจากตัวแปร order ให้รอข้อมูล จากฟังก์ชั่น getUserOrder() ก่อนนำไปใช้งาน 
  return 'Your order is: $order'; // คืนค่าข้อมูลการสั่งซื้อ
}
 
// ฟังก์ชั่นจำลอง ข้อมูลการสั่งซื้อ
Future<String> getUserOrder() {
  // จำลอง และสมมติว่า การทำงานส่่วนนี้มีความซับซ้อน และทำงานช้า
  // โดยให้ดีเลย์การคืนค่ากลับในอีก 4 วินาที
  return Future.delayed(Duration(seconds: 4), () => 'Large Latte'); 
}
 
    สิ่งที่มีการปรับเพิ่มเข้ามา เมื่อเปลี่ยนมาใช้รูปแบบการทำงานแบบ asynchronous เป็นดังนี้คือ
 
    - เดิมคำสั่ง createOrderMessage() คืนค่าขนิดข้อมูลเป็น String ก็เปลี่ยนเป็น Future<String>
    - ใช้งาน "async" keyword เพื่อกำหนดให้ฟังก์ชั่น createOrderMessage() และ main() เป็น asynchronous ฟังก์ชั่น
    - ใช้งาน "await" keyword เพื่อเรียกใช้งาน asynchronous ฟังก์ชั่น และรอผลลัพธ์สุดท้าย
 
    ทำความเข้าใจเพิ่มเติม
 
    - เราใช้ "async" keyword เพื่อระบุว่าฟังก์ชั่นนั้นๆ เป็น asynchronous
    - asynchronous ฟังก์ชั่น เป็นฟังก์ชั่นที่มีการใช้งาน "async" keyword กำกับไว้
    - เราใช้ "await" keyword เพื่อรับค่าผลลัพธ์สุดท้ายจากการเรียกใช้งาน asynchronous ฟังก์ชั่น โดยจะสามารถกำหนดได้เฉพาะ
      ภายใน asynchronous ฟังก์ชั่น เท่านั้น
 
    ถ้าสังเกตดีๆ จะเห็นว่า คำสั่ง getUserOrder() นั่นเป็นรูปแบบการทำงานแบบ asynchronous ที่มีเรื่องของเวลาที่ต้องรอเข้ามาเกี่ยวข้อง
แต่เราไม่ได้จำเป็นต้องระบุ โดยใช้ "async" keyword ก็ได้ เพราะในฟังก์ชั่นดังกล่าว เราไม่มีการเรียกใช้งาน "await" เพื่อเรียกใช้งานคำสั่งอื่น
ภายใน ต่างจากในคำสั่ง createOrderMessage() ที่มีการใช้งาน "await" keyword สำหรับเรียกใช้ asynchronous ฟังก์ชั่น จึงจำเป็นต้องระบุ
"async" keyword ให้กับ createOrderMessage() ด้วย
 
    เมื่อเรามีการปรับมาใช้งาน async ฟังก์ชั่น ทำให้การทำงานด้วยรูปแบบ asynchronous มีความต่อเนื่อง และสัมพันธ์กันมากขึ้น นั่นคือ การใช้
async ฟังก์ชั่น ช่วยให้เราได้ข้อมูลที่ต้องการจนครบถ้วนก่อน ถึงค่อยทำงานต่อไปในคำสังถัดไป มีประโยชน์ สมมติเราดึงข้อมูลจาก Web Service
หรืออ่านข้อมูลจากฐานข้อมูล เราจำเป็นต้องรอข้อมูลให้ได้มาครบถ้วนก่อน จึงจะไปจัดการกับข้อมูลนั้นๆ ต่อได้ ดังนั้น ถ้าคำสั่งแรกคือ การดึงข้อมูล
และคำสั่งที่สองคือจัดรูปแบบข้อมูลที่ได้มา เมื่อมเราใช้งาน async ฟังก์ชั่น เราก็จะได้ข้อมูลในคำสั่งแรกมาจนครบก่อน คำสั่งที่สองถึงจะทำงาน
นั่นก็คือ ต้องรอให้ async ทำงานเสร็จสิ้นเสียก่อน ถึงจะสามารถทำงานในลำดับต่อไปได้
 
    เพื่อให้เห็นลำดับ และทิศทางการทำงานชัดเจน ดูรูปแบบตัวอย่างด้านล่างนี้ประกอบ
 
// asynchronous ฟังก์ชั่น
void main () async {
  print("Run 1");
  print(await createOrderMessage());
  print("Run 2");
  print(run3());
  print("Run 4");
  print(await run5());
  print("Run 6");
}
// synchronous ฟังก์ชั่น
String run3(){
  return "Run 3";
}
// asynchronous ฟังก์ชั่น
Future<String> run5() async {
  return Future.delayed(Duration(seconds: 4), () => 'Run 5'); 
}
Future<String> createOrderMessage() async {
  var order = await getUserOrder();   
  return 'Your order is: $order'; 
}
Future<String> getUserOrder() {
  return Future.delayed(Duration(seconds: 4), () => 'Large Latte'); 
}
 
    ลำดับการทำงานคือ ทันที่โปรแกรมทำงานคำสั่ง ก่อน การเรียกใช้งาน await ตัวแรก จะทำงานทันที นั่นคือ จะมีข้อความว่า "Run 1"  แสดง
จากการใช้งานคำสั่ง print("Run 1") หลังจากนั้น 4 วินาที จะมีข้อความ 
 
    Your order is: Large Latte
    Run 2
    Run 3
    Run 4
 
   ไล่ขึ้นมาตามลำดับ พอมาถึง await ตัวที่สอง ที่เป็น async ฟังก์ชั่น ก็จะรออีก 4 วินาที ก่อนที่ข้อความ
 
    Run 5
    Run 6
 
    จะแสดงต่อมาตามลำดับ
    จะเห็นว่า flow หรือลำดับการทำงาน จะมีลักษณะที่แตกต่างจากกรณีที่เป็น การใช้งานแบบ synchronous 
 
    เราลองมาดูหากกำหนดการใช้งานในรูปแบบ synchronous  เป็นดังนี้
 
// asynchronous ฟังก์ชั่น
void main () {
  print("Run 1");
  print(createOrderMessage());
  print("Run 2");
  print(run3());
  print("Run 4");
  print(run5());
  print("Run 6");
}
// synchronous ฟังก์ชั่น
String run3(){
  return "Run 3";
}
// asynchronous ฟังก์ชั่น
Future<void> run5() {
  return Future.delayed(Duration(seconds: 4), () => print('Run 5')); 
}
String createOrderMessage()  {
  var order = getUserOrder();   
  return 'Your order is: $order'; 
}
Future<void> getUserOrder() {
  return Future.delayed(Duration(seconds: 4), () => print('Large Latte')); 
}
 
    ผลลัพธ์ที่ได้จะเป็น
 
    Run 1
    Your order is: Instance of '_Future<void>'
    Run 2
    Run 3
    Run 4
    Instance of '_Future<void>'
    Run 6
 
    คำสั่งทั้งหมดจะทำงานต่อเนื่องกันตามลำดับทันที แต่ค่าจากคำสั่ง createOrderMessage() และ run5() ที่เป็นการทำงานในรูปแบบ asynchronous
ที่มีเรื่องของเวลาที่ต้องรอเข้ามาเกี่ยวข้อง ทำให้แสดงค่า ที่เป็นค่ายังไม่เสร็จสมบูรณ์ก่อน หรือก็คือ Uncompleted ที่อธิบายไปแล้วตอนต้นด้านบน
และเมื่อครบ 4 วินาที ต่อมา ก็จะแสดงผลลัพธ์สุดท้ายของ คำสั่ง createOrderMessage() และ run5() ออกมา เป็น
 
    Large Latte
    Run 5
 
 
 

การจัดการ Error ใน asynchronous ฟังก์ชั่น

    ในกรณีที่เราต้องการจัดการกับ errror ที่เกิดขึ้นเมื่อมีการใช้งาน async ฟังก์ชั่น เราสามารถใช้ try-catch ในรูปแบบดังต่อไปนี้ได้
ยกตัวอย่างเช่น
 
void main () async {
  print(await createOrderMessage());
}
Future<String> createOrderMessage() async {
  try {
    var order = await getUserOrder();
    print('Awaiting user order...');
    return 'Your order is: $order'; 
  } catch (err) {
    return 'Caught error: $err';
  }    
}
Future<String> getUserOrder() {
  // สมมติกรณี error
  return Future.delayed(Duration(seconds: 3), 
    () => throw Exception('Logout failed: user ID is invalid'));
}
 
    เนื่องจากคำสั่ง getUserOrder() ในตัวอย่าง เราสมมติให้เกิด error เมื่อมีการเรียกใช้งาน ดังนั้น ผลลัพธ์สุดท้าย หลังจากใช้คำสั่ง try เพื่อ
เรียกดูข้อมูลการสั่งซื้อ แล้วเกิด error ขึ้น จึงเข้าเงื่อนไข catch error ขึ้น แล้วส่งกลับข้อความ error กลับออกมาเป็นดังนี้
 
Caught error: Exception: Logout failed: user ID is invalid
 
 
 
    หวังว่าเนื้อหาเกี่ยวกับการใช้าน asynchronous ฟังก์ชั่น จะเป็นแนวทาง เพื่อนำไปประยุกต์ใช้งาน และทำความเข้าใจเพิ่มเติมต่อไป


กด Like หรือ Share เป็นกำลังใจ ให้มีบทความใหม่ๆ เรื่อยๆ น่ะครับ



อ่านต่อที่บทความ









เนื้อหาที่เกี่ยวข้อง









URL สำหรับอ้างอิง





คำแนะนำ และการใช้งาน

สมาชิก กรุณา ล็อกอินเข้าระบบ เพื่อตั้งคำถามใหม่ หรือ ตอบคำถาม สมาชิกใหม่ สมัครสมาชิกได้ที่ สมัครสมาชิก


  • ถาม-ตอบ กรุณา ล็อกอินเข้าระบบ
  • เปลี่ยน


    ( หรือ เข้าใช้งานผ่าน Social Login )







เว็บไซต์ของเราให้บริการเนื้อหาบทความสำหรับนักพัฒนา โดยพึ่งพารายได้เล็กน้อยจากการแสดงโฆษณา โปรดสนับสนุนเว็บไซต์ของเราด้วยการปิดการใช้งานตัวปิดกั้นโฆษณา (Disable Ads Blocker) ขอบคุณครับ