ไม่ได้สัญญาไว้เพียงแค่โทรกลับ


430

ฉันพัฒนา JavaScript มาหลายปีแล้วและฉันก็ไม่เข้าใจว่าสัญญาจะเกิดอะไรขึ้น

ดูเหมือนว่าทั้งหมดที่ฉันทำคือการเปลี่ยนแปลง:

api(function(result){
    api2(function(result2){
        api3(function(result3){
             // do work
        });
    });
});

ซึ่งฉันสามารถใช้ห้องสมุดเช่นasyncสำหรับต่อไปกับสิ่งที่ชอบ

api().then(function(result){
     api2().then(function(result2){
          api3().then(function(result3){
               // do work
          });
     });
});

รหัสไหนมากกว่าและอ่านได้น้อยกว่า ฉันไม่ได้อะไรเลยนี่มันไม่ได้ 'แบน' อย่างน่าอัศจรรย์ ไม่ต้องพูดถึงต้องเปลี่ยนสิ่งต่าง ๆ เพื่อสัญญา

ดังนั้นเอะอะใหญ่เกี่ยวกับสัญญาที่นี่คืออะไร?


11
ในหัวข้อ : มีบทความที่ให้ข้อมูลเกี่ยวกับสัญญาใน Html5Rocks: html5rocks.com/en/tutorials/es6/promises จริง ๆ
ComFreek

2
Fyi คำตอบที่คุณยอมรับนั้นเป็นรายการเก่า ๆ ของผลประโยชน์เล็กน้อยที่ไม่ใช่ประเด็นของสัญญาเลยและไม่ได้โน้มน้าวให้ฉันใช้สัญญา: / สิ่งที่ทำให้ฉันเชื่อมั่นในการใช้สัญญาคือด้าน DSL ตามที่อธิบายไว้ในคำตอบของ Oscar
Esailija

@Eailija สบายดี leet ของคุณพูดทำให้ฉันมั่นใจ ฉันยอมรับคำตอบอื่น ๆ แม้ว่าฉันคิดว่า Bergi คนหนึ่งให้คะแนนดีมาก (และแตกต่าง) เช่นกัน
Benjamin Gruenbaum

@Esailija "สิ่งที่ทำให้ฉันมั่นใจในการใช้สัญญาคือด้าน DSL ตามที่อธิบายไว้ในคำตอบของออสการ์" << "DSL" คืออะไร? และ "มุมมอง DSL" ที่คุณอ้างถึงคืออะไร
monsto

1
@monsto: DSL: Domain Specific Language เป็นภาษาที่ออกแบบมาเพื่อใช้ในชุดย่อยของระบบ (เช่น SQL หรือ ORM เพื่อพูดคุยกับฐานข้อมูล, regex เพื่อค้นหารูปแบบ, ฯลฯ ) ในบริบทนี้ "DSL" เป็น API ของสัญญาซึ่งถ้าคุณจัดโครงสร้างโค้ดของคุณในแบบที่ออสการ์ทำได้เกือบจะเหมือนกับน้ำตาลซินแทคติกที่เสริม JavaScript เพื่อระบุบริบทเฉพาะของการดำเนินการ async คำสัญญาสร้างสำนวนบางอย่างที่ทำให้พวกมันกลายเป็นภาษาที่ออกแบบมาเพื่อให้โปรแกรมเมอร์เข้าใจการไหลของจิตใจในโครงสร้างประเภทนี้ได้ง่ายขึ้น
Michael Ekoka

คำตอบ:


631

คำสัญญาไม่ใช่การเรียกกลับ สัญญาหมายถึงผลในอนาคตของการดำเนินการไม่ตรงกัน แน่นอนการเขียนพวกเขาในแบบที่คุณทำคุณจะได้รับประโยชน์น้อย แต่ถ้าคุณเขียนถึงวิธีการใช้งานคุณสามารถเขียนโค้ดแบบอะซิงโครนัสในลักษณะที่คล้ายกับรหัสซิงโครนัสและง่ายต่อการติดตามมากขึ้น:

api().then(function(result){
    return api2();
}).then(function(result2){
    return api3();
}).then(function(result3){
     // do work
});

แน่นอนว่าไม่น้อยรหัส แต่อ่านได้มากขึ้น

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

api().then(function(result){
    return api2();
}).then(function(result2){
    return api3();
}).then(function(result3){
     // do work
}).catch(function(error) {
     //handle any error that may occur before this point
});

สวยมากเหมือนtry { ... } catchบล็อก

ดียิ่งขึ้น:

api().then(function(result){
    return api2();
}).then(function(result2){
    return api3();
}).then(function(result3){
     // do work
}).catch(function(error) {
     //handle any error that may occur before this point
}).then(function() {
     //do something whether there was an error or not
     //like hiding an spinner if you were performing an AJAX request.
});

และดียิ่งขึ้น: เกิดอะไรขึ้นถ้าทั้ง 3 โทรไปapi, api2, api3สามารถทำงานพร้อมกัน (เช่นถ้าพวกเขาโทร AJAX) แต่คุณจำเป็นต้องรอสาม? หากไม่มีสัญญาคุณควรสร้างตัวนับจำนวนหนึ่ง ด้วยสัญญาที่ใช้สัญกรณ์ ES6 เป็นเค้กอีกชิ้นและเรียบร้อยดี:

Promise.all([api(), api2(), api3()]).then(function(result) {
    //do work. result is an array contains the values of the three fulfilled promises.
}).catch(function(error) {
    //handle the error. At least one of the promises rejected.
});

หวังว่าคุณจะเห็นสัญญาในมุมมองใหม่ตอนนี้


124
พวกเขาไม่ควรตั้งชื่อมันว่า "สัญญา" "อนาคต" ดีกว่าอย่างน้อย 100x
Pacerier

12
@Pacerier เพราะ jQuery ไม่ได้มีอนาคตที่บริสุทธิ์
Esailija

5
รูปแบบอื่น (ขึ้นอยู่กับสิ่งที่ต้องการ: api (). แล้ว (api2). แล้ว (api3). แล้ว (doWork) นั่นคือถ้าฟังก์ชั่น api2 / api3 รับอินพุตจากขั้นตอนสุดท้ายและกลับสัญญาใหม่ด้วยตนเองพวกเขา สามารถถูกล่ามโซ่โดยไม่ต้องห่อพิเศษนั่นคือพวกเขาเขียน
Dtipson

1
เกิดอะไรขึ้นถ้ามีการดำเนินการ async ในapi2และapi3? จะ.thenเรียกได้ครั้งสุดท้ายเมื่อการดำเนินการ async นั้นเสร็จสมบูรณ์
NiCk Newman

8
ทำไมคุณติดแท็กฉัน ฉันเพิ่งแก้ไขไวยากรณ์เล็กน้อย ฉันไม่ใช่ผู้เชี่ยวชาญ JS :)
Scott Arciszewski

169

ใช่คำสัญญาเป็นการเรียกกลับแบบอะซิงโครนัส พวกเขาไม่สามารถทำสิ่งใด ๆ ที่การเรียกกลับไม่สามารถทำได้และคุณประสบปัญหาเดียวกันกับอะซิงโครนัสเช่นเดียวกับการโทรกลับธรรมดา

อย่างไรก็ตามสัญญามีมากขึ้นกว่าเพียงแค่การเรียกกลับ พวกมันเป็นสิ่งที่เป็นนามธรรมอย่างยิ่งช่วยให้โค้ดที่สะอาดและดีกว่าทำงานได้ดีขึ้น

ดังนั้นแนวคิดหลักคืออะไร

สัญญาเป็นวัตถุที่แสดงผลลัพธ์ของการคำนวณเดียว (แบบอะซิงโครนัส) พวกเขาแก้ไขผลลัพธ์นั้นเพียงครั้งเดียว มีบางสิ่งที่ความหมายนี้คือ:

สัญญาใช้รูปแบบการสังเกตการณ์:

  • คุณไม่จำเป็นต้องรู้การเรียกกลับที่จะใช้ค่าก่อนที่งานจะเสร็จสมบูรณ์
  • แทนที่จะคาดหวังว่าการเรียกกลับเป็นอาร์กิวเมนต์สำหรับฟังก์ชั่นของคุณคุณสามารถreturnเป็นวัตถุสัญญาได้อย่างง่ายดาย
  • สัญญาจะเก็บค่าและคุณสามารถโปร่งใสเพิ่มโทรกลับเมื่อใดก็ตามที่คุณต้องการ มันจะถูกเรียกเมื่อผลลัพธ์ที่มีอยู่ "ความโปร่งใส" หมายความว่าเมื่อคุณมีสัญญาและเพิ่มการติดต่อกลับมันไม่ได้สร้างความแตกต่างให้กับรหัสของคุณไม่ว่าผลลัพธ์จะมาถึงก็ตาม - API และสัญญาต่าง ๆ นั้นมีความเหมือนกัน
  • คุณสามารถเพิ่มการโทรกลับหลายรายการได้อย่างง่ายดาย

สัญญามี chainable ( เอก , ถ้าคุณต้องการ ):

  • หากคุณต้องการแปลงค่าที่สัญญาแสดงไว้คุณจะแมปฟังก์ชันการแปลงเหนือสัญญาและรับสัญญาใหม่ที่แสดงผลลัพธ์ที่แปลงแล้ว คุณไม่สามารถรับค่าที่จะใช้พร้อมกันได้ แต่คุณสามารถยกระดับการเปลี่ยนแปลงในบริบทของสัญญาได้อย่างง่ายดาย ไม่มีการโทรกลับสำเร็จรูป
  • หากคุณต้องการเชื่อมโยงสองภารกิจอะซิงโครนัสคุณสามารถใช้.then()วิธีการนี้ได้ มันจะใช้การเรียกกลับที่จะเรียกด้วยผลแรกและส่งกลับสัญญาสำหรับผลของสัญญาที่โทรกลับกลับมา

ฟังดูซับซ้อนไหม? เวลาสำหรับตัวอย่างรหัส

var p1 = api1(); // returning a promise
var p3 = p1.then(function(api1Result) {
    var p2 = api2(); // returning a promise
    return p2; // The result of p2 …
}); // … becomes the result of p3

// So it does not make a difference whether you write
api1().then(function(api1Result) {
    return api2().then(console.log)
})
// or the flattened version
api1().then(function(api1Result) {
    return api2();
}).then(console.log)

ความเรียบไม่ได้มาอย่างน่าอัศจรรย์ แต่คุณสามารถทำได้อย่างง่ายดาย สำหรับตัวอย่างที่ซ้อนกันอย่างมากของคุณค่าเทียบเท่า (ใกล้) จะเป็น

api1().then(api2).then(api3).then(/* do-work-callback */);

หากเห็นรหัสของวิธีการเหล่านี้จะช่วยให้ความเข้าใจที่นี่เป็นส่วนใหญ่ lib สัญญาขั้นพื้นฐานในไม่กี่บรรทัด

เอะอะใหญ่เกี่ยวกับสัญญาคืออะไร?

คำสัญญาที่เป็นนามธรรมช่วยให้การจัดองค์ประกอบฟังก์ชั่นดีขึ้นมาก ตัวอย่างเช่นถัดจากthenการผูกมัดallฟังก์ชันสร้างสัญญาสำหรับผลลัพธ์ที่รวมกันของสัญญาที่รอแบบขนานหลายรายการ

สุดท้าย แต่ไม่ท้ายสุดสัญญามาพร้อมกับการจัดการข้อผิดพลาดแบบรวม ผลของการคำนวณอาจเป็นได้ว่าคำสัญญานั้นได้รับการเติมคุณค่าหรือถูกปฏิเสธด้วยเหตุผล ฟังก์ชันการจัดองค์ประกอบทั้งหมดจะจัดการสิ่งนี้โดยอัตโนมัติและเผยแพร่ข้อผิดพลาดในกลุ่มสัญญาเพื่อที่คุณจะได้ไม่ต้องสนใจมันอย่างชัดเจนทุกที่ - ตรงกันข้ามกับการใช้งานการติดต่อกลับแบบธรรมดา ในท้ายที่สุดคุณสามารถเพิ่มการเรียกกลับข้อผิดพลาดเฉพาะสำหรับข้อยกเว้นที่เกิดขึ้นทั้งหมด

ไม่ต้องพูดถึงต้องเปลี่ยนสิ่งต่าง ๆ เพื่อสัญญา

นั่นเป็นเรื่องเล็กน้อยที่จริงแล้วมีห้องสมุดสัญญาที่ดีดูฉันจะแปลง callback API ที่มีอยู่เป็นสัญญาได้อย่างไร


สวัสดี Bergi คุณจะมีอะไรน่าสนใจที่จะเพิ่มคำถามนี้หรือไม่? stackoverflow.com/questions/22724883/…
Sebastien Lorber

1
@Sebastien: ผมไม่ทราบว่ามากเกี่ยวกับสกาล่า (ยัง) และฉันเท่านั้นที่สามารถทำซ้ำสิ่งที่เบนจามินกล่าวว่า :-)
Bergi

3
ข้อสังเกตเล็กน้อย: คุณไม่สามารถใช้งานได้.then(console.log)เนื่องจาก console.log ขึ้นอยู่กับบริบทของคอนโซล วิธีนี้จะทำให้เกิดข้อผิดพลาดในการเรียกที่ผิดกฎหมาย ใช้console.log.bind(console)หรือx => console.log(x)เพื่อเชื่อมโยงบริบท
Tamas Hegedus

3
@hege_hegedus: มีสภาพแวดล้อมที่consoleวิธีการผูกไว้แล้ว และแน่นอนฉันแค่บอกว่าทั้งสองรังมีพฤติกรรมเหมือนกันทุกอย่างไม่ทำงานใด ๆ :-P
Bergi

1
มันเยี่ยมมาก นี่คือสิ่งที่ฉันต้องการ: โค้ดน้อยลงและการตีความเพิ่มเติม ขอบคุณ.
Adam Patterson

21

นอกจากนี้ยังมีคำตอบที่จัดตั้งขึ้นแล้วกับ ES6 ลูกศรฟังก์ชั่นสัญญาเปิดจากสุภาพส่องแสงสีฟ้าขนาดเล็กแคระตรงกลายเป็นดาวยักษ์แดง นั่นกำลังจะล่มสลายลงในซูเปอร์โนวา:

api().then(result => api2()).then(result2 => api3()).then(result3 => console.log(result3))

ดังที่oligofrenชี้ให้เห็นโดยไม่มีข้อโต้แย้งระหว่าง api call คุณไม่จำเป็นต้องใช้ฟังก์ชั่น wrapper ที่ไม่ระบุชื่อเลย:

api().then(api2).then(api3).then(r3 => console.log(r3))

และในที่สุดหากคุณต้องการที่จะไปถึงระดับหลุมดำมวลมหาศาลสัญญาได้ถูกรอคอย:

async function callApis() {
    let api1Result = await api();
    let api2Result = await api2(api1Result);
    let api3Result = await api3(api2Result);

    return api3Result;
}

9
"ด้วยฟังก์ชั่นลูกศร ES6 คำสัญญาเปลี่ยนจากดาวสีน้ำเงินขนาดเล็กที่ส่องแสงเป็นดาวยักษ์แดงอย่างสุภาพซึ่งกำลังจะล่มสลายลงในซูเปอร์โนวา" การแปล: การรวมฟังก์ชั่นลูกศร ES6 กับ Promises นั้นยอดเยี่ยม :)
user3344977

3
นั่นทำให้เสียง Promises เหมือนหายนะของจักรวาลซึ่งฉันไม่คิดว่าเป็นความตั้งใจของคุณ
Michael McGinnis

หากคุณไม่ได้ใช้การขัดแย้งในวิธีการคุณอาจรวมทั้งฟังก์ชั่นข้ามลูกศรสิ้นเชิงapiX api().then(api2).then(api3).then(r3 => console.log(r3))
oligofren

@MichaelMcGinnis - ผลประโยชน์ที่ได้รับของสัญญากับนรกโทรกลับที่น่าเบื่อเหมือนซูเปอร์โนวาที่ระเบิดในมุมมืดของอวกาศ
John Weisz

ฉันรู้ว่าคุณหมายถึงมันเป็นบทกวี แต่สัญญาค่อนข้างห่างไกลจาก "ซูเปอร์โนวา" การฝ่าฝืนกฎหมายเกี่ยวกับการเป็นเอกเทศหรือขาดการสนับสนุนกรณีการใช้งานที่เป็นประโยชน์มากขึ้นเช่นการยกเลิกหรือคืนค่าหลายค่า
Dmitri Zaitsev

15

นอกจากคำตอบที่ดีเลิศข้างต้นแล้วอาจมีการเพิ่ม 2 คะแนน

1. ความแตกต่างทางความหมาย:

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

ในทางกลับกันการโทรกลับจัดการกับเหตุการณ์ ดังนั้นหากเหตุการณ์ที่คุณสนใจเกิดขึ้นก่อนที่การลงทะเบียนโทรกลับจะไม่ถูกเรียกกลับ

2. การผกผันของการควบคุม

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

อ้างถึงห่วงเหตุการณ์ Javascriptสำหรับคำอธิบาย

ด้วยPromisesการควบคุมจะอยู่กับโปรแกรมการโทร . แล้ว () วิธีการอาจถูกเรียกได้ตลอดเวลาถ้าเราเก็บวัตถุสัญญา


1
ฉันไม่รู้ว่าทำไม แต่นี่ดูเหมือนจะเป็นคำตอบที่ดีกว่า
radiantshaw

13

นอกเหนือจากคำตอบอื่น ๆ แล้วไวยากรณ์ ES2015 ยังผสานอย่างกลมกลืนกับสัญญาลดรหัสหม้อไอน้ำมากขึ้น:

// Sequentially:
api1()
  .then(r1 => api2(r1))
  .then(r2 => api3(r2))
  .then(r3 => {
      // Done
  });

// Parallel:
Promise.all([
    api1(),
    api2(),
    api3()
]).then(([r1, r2, r3]) => {
    // Done
});

5

คำสัญญาไม่ใช่การเรียกกลับทั้งสองเป็นสำนวนการเขียนโปรแกรมที่อำนวยความสะดวกการเขียนโปรแกรม async การใช้ async / await-style ของการเขียนโปรแกรมโดยใช้ coroutines หรือเครื่องกำเนิดไฟฟ้าที่ส่งคืนสัญญาถือได้ว่าเป็นสำนวนที่ 3 การเปรียบเทียบสำนวนเหล่านี้ในภาษาการเขียนโปรแกรมที่แตกต่างกัน (รวมถึง Javascript) อยู่ที่นี่: https://github.com/KjellSchubert/promise-future-task


5

ไม่เลย.

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

อันที่จริงใน JavaScript, ฟังก์ชั่นของตัวเองถือเป็นวัตถุและด้วยเหตุนี้เป็นวัตถุอื่น ๆ ฟังก์ชั่นยังสามารถถูกส่งไปเป็นข้อโต้แย้งกับคนอื่น ๆฟังก์ชั่น กรณีการใช้งานทั่วไปและทั่วไปที่ใคร ๆ ก็นึกถึงคือฟังก์ชัน setTimeout () ใน JavaScript

คำสัญญาไม่มีอะไรนอกจากวิธีการจัดการและจัดโครงสร้างโค้ดแบบอะซิงโครนัสที่ไม่ได้ปรับปรุงอย่างมากเมื่อเปรียบเทียบกับการโทรกลับ

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


2

ไม่มีสัญญาใดที่จะคลุมเครือในการโทรกลับ

ตัวอย่างคุณสามารถใช้สัญญาดั้งเดิมของ javascript กับโหนด js

my cloud 9 code link : https://ide.c9.io/adx2803/native-promises-in-node

/**
* Created by dixit-lab on 20/6/16.
*/

var express = require('express');
var request = require('request');   //Simplified HTTP request client.


var app = express();

function promisify(url) {
    return new Promise(function (resolve, reject) {
    request.get(url, function (error, response, body) {
    if (!error && response.statusCode == 200) {
        resolve(body);
    }
    else {
        reject(error);
    }
    })
    });
}

//get all the albums of a user who have posted post 100
app.get('/listAlbums', function (req, res) {
//get the post with post id 100
promisify('http://jsonplaceholder.typicode.com/posts/100').then(function (result) {
var obj = JSON.parse(result);
return promisify('http://jsonplaceholder.typicode.com/users/' + obj.userId + '/albums')
})
.catch(function (e) {
    console.log(e);
})
.then(function (result) {
    res.end(result);
}
)

})


var server = app.listen(8081, function () {

var host = server.address().address
var port = server.address().port

console.log("Example app listening at http://%s:%s", host, port)

})


//run webservice on browser : http://localhost:8081/listAlbums

1

จาวาสคริปต์สัญญาใช้ฟังก์ชั่นการโทรกลับเพื่อกำหนดสิ่งที่ต้องทำหลังจากสัญญาได้รับการแก้ไขหรือปฏิเสธดังนั้นทั้งสองจึงไม่แตกต่างกันโดยพื้นฐาน แนวคิดหลักที่อยู่เบื้องหลังคำสัญญาคือการใช้การเรียกกลับ - โดยเฉพาะอย่างยิ่งการโทรกลับซ้อนที่คุณต้องการดำเนินการบางอย่าง แต่จะสามารถอ่านได้มากขึ้น


0

ภาพรวมสัญญา:

ใน JS เราสามารถสรุปการทำงานแบบอะซิงโครนัส (เช่นการเรียกฐานข้อมูลการโทร AJAX) ตามสัญญา โดยปกติเราต้องการรันตรรกะเพิ่มเติมบางอย่างกับข้อมูลที่ดึงมา JS สัญญามีฟังก์ชันตัวจัดการซึ่งประมวลผลผลลัพธ์ของการดำเนินการแบบอะซิงโครนัส ฟังก์ชันตัวจัดการสามารถมีการดำเนินการแบบอะซิงโครนัสอื่น ๆ ภายในซึ่งอาจขึ้นอยู่กับค่าของการดำเนินการแบบอะซิงโครนัสก่อนหน้า

คำสัญญามีสถานะดังต่อไปนี้ 3 สถานะเสมอ:

  1. รอดำเนินการ: สถานะเริ่มต้นของทุกสัญญาไม่สมบูรณ์หรือปฏิเสธ
  2. สำเร็จแล้ว: การดำเนินการเสร็จสมบูรณ์
  3. ปฏิเสธ: การดำเนินการล้มเหลว

สัญญาที่รอดำเนินการสามารถแก้ไข / เติมเต็มหรือปฏิเสธด้วยค่า ดังนั้นเมธอดตัวจัดการต่อไปนี้ซึ่งรับการเรียกกลับเป็นอาร์กิวเมนต์จะถูกเรียก:

  1. Promise.prototype.then() : เมื่อสัญญาถูกแก้ไขอาร์กิวเมนต์การเรียกกลับของฟังก์ชันนี้จะถูกเรียก
  2. Promise.prototype.catch() : เมื่อสัญญาถูกปฏิเสธอาร์กิวเมนต์โทรกลับของฟังก์ชันนี้จะถูกเรียก

แม้ว่าทักษะวิธีการข้างต้นจะได้รับอาร์กิวเมนต์การเรียกกลับที่เหนือกว่าการใช้การเรียกกลับที่นี่เท่านั้นเป็นตัวอย่างที่จะอธิบายให้ชัดเจนมาก:

ตัวอย่าง

function createProm(resolveVal, rejectVal) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            if (Math.random() > 0.5) {
                console.log("Resolved");
                resolve(resolveVal);
            } else {
                console.log("Rejected");
                reject(rejectVal);
            }
        }, 1000);
    });
}

createProm(1, 2)
    .then((resVal) => {
        console.log(resVal);
        return resVal + 1;
    })
    .then((resVal) => {
        console.log(resVal);
        return resVal + 2;
    })
    .catch((rejectVal) => {
        console.log(rejectVal);
        return rejectVal + 1;
    })
    .then((resVal) => {
        console.log(resVal);
    })
    .finally(() => {
        console.log("Promise done");
    });

  • ฟังก์ชั่น createProm สร้างสัญญาที่ได้รับการแก้ไขหรือปฏิเสธขึ้นอยู่กับการสุ่ม Nr หลังจาก 1 วินาที
  • หากสัญญาได้รับการแก้ไขthenวิธีการแรกจะถูกเรียกและค่าที่แก้ไขจะถูกส่งผ่านเป็นอาร์กิวเมนต์ของการเรียกกลับ
  • หากสัญญาถูกปฏิเสธcatchวิธีแรกจะถูกเรียกและค่าที่ถูกปฏิเสธจะถูกส่งผ่านเป็นอาร์กิวเมนต์
  • catchและthenวิธีการกลับคำสัญญาที่ว่าทำไมเราสามารถโซ่พวกเขา พวกเขาตัดค่าใด ๆ กลับมาPromise.resolveและความคุ้มค่าโยนใด ๆ (โดยใช้throwคำสำคัญ) Promise.rejectใน ดังนั้นค่าใด ๆ ที่ส่งคืนจะถูกแปลงเป็นสัญญาและในสัญญานี้เราสามารถเรียกฟังก์ชันตัวจัดการได้อีกครั้ง
  • โซ่สัญญาทำให้เราควบคุมได้ดียิ่งขึ้นและภาพรวมที่ดีกว่าการโทรกลับซ้อนกัน ตัวอย่างเช่นcatchวิธีการจัดการข้อผิดพลาดทั้งหมดที่เกิดขึ้นก่อนที่จะcatchจัดการ
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.