ก่อนที่เราจะเริ่มต้นการแนะนำอย่างเป็นทางการเราต้องการดูว่าคำสัญญา JavaScript เป็นอย่างไร:
การคัดลอกรหัสมีดังนี้:
var p = สัญญาใหม่ (ฟังก์ชั่น (แก้ไข, ปฏิเสธ) {
แก้ไข ("Hello World");
-
P.then (ฟังก์ชั่น (str) {
การแจ้งเตือน (STR);
-
1. จากนั้น () ส่งคืนสัญญาที่ถูกแยกออก
ความแตกต่างระหว่างสองรหัสต่อไปนี้คืออะไร?
การคัดลอกรหัสมีดังนี้:
// จัดแสดงก
var p = สัญญาใหม่ (/*...*/);
P.then (func1);
P.then (func2);
// จัดแสดง b
var p = สัญญาใหม่ (/*...*/);
P.then (func1)
. จากนั้น (func2);
หากคุณพิจารณารหัสสองชิ้นข้างต้นอย่างรอบคอบที่เทียบเท่ากันคำสัญญานั้นเป็นเพียงอาร์เรย์หนึ่งมิติของฟังก์ชั่นการโทรกลับ อย่างไรก็ตามนี่ไม่ใช่กรณี จากนั้น () การโทรกลับจะส่งคืนสัญญาที่ถูกแยกออก ดังนั้นในนิทรรศการหาก func1 () โยนข้อยกเว้น func2 () ยังคงเรียกว่าปกติ
ใน ExhibitB หาก func1 () ส่งข้อผิดพลาด fun2 () จะไม่ถูกเรียกเพราะการโทรครั้งแรกส่งคืนสัญญาใหม่ซึ่งจะถูกปฏิเสธใน func1 () ผลที่ได้คือ Func2 () ถูกข้ามไป
สรุป: สัญญาสามารถแยกออกเป็นหลายเส้นทางคล้ายกับผังงานที่ซับซ้อน
2. การโทรกลับควรผ่านผลลัพธ์
อะไรจะได้รับคำเตือนเมื่อคุณเรียกใช้รหัสต่อไปนี้?
การคัดลอกรหัสมีดังนี้:
var p = สัญญาใหม่ (ฟังก์ชั่น (แก้ไข, ปฏิเสธ) {
แก้ไข ("Hello World");
-
P.then (ฟังก์ชั่น (str) {})
. แล้ว (ฟังก์ชั่น (str) {
การแจ้งเตือน (STR);
-
การแจ้งเตือนในวินาทีนั้น () ไม่แสดงอะไรเลย นี่เป็นเพราะฟังก์ชั่นการโทรกลับในบริบทของสัญญาไม่มีฟังก์ชั่นการโทรกลับเนื่องจากผลลัพธ์เปลี่ยนไป สัญญาคาดว่าการโทรกลับของคุณจะส่งคืนผลลัพธ์เดียวกันหรือผลการแทนที่ซึ่งจะถูกส่งผ่านไปยังการโทรกลับครั้งถัดไป
คล้ายกับการใช้ adpater เพื่อเปลี่ยนผลลัพธ์ดังนี้:
การคัดลอกรหัสมีดังนี้:
var feettometres = function (ft) {return ft*12*0.0254};
var p = สัญญาใหม่ (/*...*/);
P.then (feettometres)
. แล้ว (ฟังก์ชั่น (เมตร) {
การแจ้งเตือน (เมตร);
-
3. มีเพียงข้อยกเว้นจากเลเยอร์ก่อนหน้าเท่านั้น
ความแตกต่างระหว่างรหัสสองชิ้นนี้แตกต่างกันอย่างไร?
การคัดลอกรหัสมีดังนี้:
// จัดแสดงก
สัญญาใหม่ (ฟังก์ชั่น (แก้ไข, ปฏิเสธ) {
แก้ไข ("Hello World");
-
.แล้ว(
ฟังก์ชั่น (str) {
โยนข้อผิดพลาดใหม่ ("uh oh");
-
ไม่ได้กำหนด
-
.แล้ว(
ไม่ได้กำหนด
ฟังก์ชั่น (ข้อผิดพลาด) {
การแจ้งเตือน (ข้อผิดพลาด);
-
-
// จัดแสดง b
สัญญาใหม่ (ฟังก์ชั่น (แก้ไข, ปฏิเสธ) {
แก้ไข ("Hello World");
-
.แล้ว(
ฟังก์ชั่น (str) {
โยนข้อผิดพลาดใหม่ ("uh oh");
-
ฟังก์ชั่น (ข้อผิดพลาด) {
การแจ้งเตือน (ข้อผิดพลาด);
-
-
ในรหัสชิ้นแรกข้อยกเว้นในตอนแรก () จะถูกโยนและจะถูกจับโดยที่สองจากนั้น () และคำเตือน "uh oh" จะถูกเรียกใช้ คู่มือนี้มีข้อยกเว้นเฉพาะในระดับก่อนหน้าจะถูกจับได้
ในรหัสชิ้นที่สองฟังก์ชั่นการโทรกลับและฟังก์ชั่นการเรียกกลับข้อผิดพลาดอยู่ในระดับเดียวกันซึ่งหมายความว่าเมื่อมีการโยนข้อยกเว้นในการโทรกลับมันจะไม่ถูกจับ ในความเป็นจริงการโทรกลับข้อผิดพลาดของรหัสที่สองจะถูกโยนลงเมื่อสัญญาถูกปฏิเสธหรือหากสัญญานั้นผิด
4. ข้อผิดพลาดสามารถกู้คืนได้
ในฟังก์ชั่นการโทรกลับข้อผิดพลาดหากคุณไม่ได้โยนข้อผิดพลาดอีกครั้งสัญญาจะถือว่าคุณได้กู้คืนจากข้อผิดพลาดและกลับเข้าสู่สถานะที่ได้รับการแก้ไข ในตัวอย่างถัดไป "ฉันบันทึกไว้" จะปรากฏขึ้นเนื่องจากข้อผิดพลาดในการโทรกลับในตอนแรก () ไม่ได้โยนข้อยกเว้นอีกครั้ง
การคัดลอกรหัสมีดังนี้:
var p = สัญญาใหม่ (ฟังก์ชั่น (แก้ไข, ปฏิเสธ) {
ปฏิเสธ (ข้อผิดพลาดใหม่ ("pebkac"));
-
p. แล้ว (
ไม่ได้กำหนด
ฟังก์ชั่น (ข้อผิดพลาด) {}
-
.แล้ว(
ฟังก์ชั่น (str) {
การแจ้งเตือน ("ฉันบันทึกไว้!");
-
ฟังก์ชั่น (ข้อผิดพลาด) {
การแจ้งเตือน ("คอมพิวเตอร์ไม่ดี!");
-
-
สัญญาสามารถถูกมองว่าเป็นเลเยอร์บนหัวหอม แต่ละ () เพิ่มระดับอื่นให้กับหัวหอม แต่ละระดับแสดงถึงกิจกรรมที่ประมวลผล เมื่อลำดับชั้นเสร็จสิ้นผลลัพธ์จะได้รับการแก้ไขและพร้อมสำหรับลำดับชั้นต่อไป
5. สัญญาสามารถระงับได้
เนื่องจากคุณพร้อมที่จะดำเนินการในวิธีหนึ่ง () วิธีการ () จึงไม่ได้หมายความว่าคุณไม่สามารถหยุดชั่วคราวและเรียกใช้ล่วงหน้าได้ล่วงหน้า เพื่อที่จะหยุดสัญญาปัจจุบันชั่วคราวหรือปล่อยให้มันรอสัญญาอื่นให้เสร็จสมบูรณ์เพียงคืนสัญญาอื่นในตอนนั้น ()
การคัดลอกรหัสมีดังนี้:
var p = สัญญาใหม่ (/*...*/);
P.then (ฟังก์ชั่น (str) {
ถ้า (! loggedin) {
คืนสัญญาใหม่ (/*...*/);
-
-
. แล้ว (ฟังก์ชั่น (str) {
การแจ้งเตือน ("เสร็จแล้ว");
-
ในรหัสก่อนหน้าพรอมต์จะไม่ปรากฏจนกว่าสัญญาใหม่จะถูกแยกวิเคราะห์ นี่เป็นวิธีที่สะดวกในการแนะนำการพึ่งพามากขึ้นในเส้นทางรหัสอะซิงโครนัสที่มีอยู่ ตัวอย่างเช่นคุณอาจพบว่าเซสชันผู้ใช้มีการหมดเวลาและคุณอาจต้องการเริ่มต้นการเข้าสู่ระบบครั้งที่สองก่อนที่จะดำเนินการต่อด้วยเส้นทางรหัสก่อนหน้า
6. สัญญาที่ได้รับการแก้ไขจะไม่ถูกดำเนินการทันที
คุณจะได้รับกล่องพรอมต์เมื่อเรียกใช้รหัสต่อไปนี้หรือไม่?
การคัดลอกรหัสมีดังนี้:
ฟังก์ชั่น runme () {
var i = 0;
สัญญาใหม่ (ฟังก์ชั่น (แก้ไข) {
แก้ไข ();
-
. แล้ว (ฟังก์ชั่น () {
i += 2;
-
การแจ้งเตือน (i);
-
เนื่องจากสัญญาจะถูกแยกวิเคราะห์ทันทีและจากนั้น () วิธีการถูกดำเนินการทันทีคุณอาจคิดว่าพรอมต์ 2 จะถูกตรวจสอบ อย่างไรก็ตามคำจำกัดความของสัญญากำหนดให้การโทรทั้งหมดถูกบังคับแบบอะซิงโครนัส ดังนั้นพรอมต์จะถูกสร้างขึ้นก่อนที่จะมีการแก้ไข