คำสัญญาสามารถ "จัดการ" ได้หลังจากถูกปฏิเสธ นั่นคือเราสามารถเรียกการปฏิเสธการโทรของสัญญาก่อนที่จะให้จัดการจับ พฤติกรรมนี้ค่อนข้างน่ารำคาญสำหรับฉันเพราะสามารถเขียน ...
var promise = new Promise(function(resolve) {
kjjdjf(); // this function does not exist });
... และในกรณีนี้สัญญาถูกปฏิเสธอย่างเงียบ ๆ หากลืมที่จะเพิ่มตัวจัดการการจับรหัสจะยังคงทำงานโดยไม่มีข้อผิดพลาด สิ่งนี้อาจนำไปสู่ข้อผิดพลาดที่เอ้อระเหยและหายาก
ในกรณีของ Node.js มีการพูดถึงการจัดการการปฏิเสธสัญญาเหล่านี้และการรายงานปัญหา นี่นำฉันมาสู่ ES7 async / คอย ลองพิจารณาตัวอย่างนี้:
async function getReadyForBed() {
let teethPromise = brushTeeth();
let tempPromise = getRoomTemperature();
// Change clothes based on room temperature
let temp = await tempPromise;
// Assume `changeClothes` also returns a Promise
if(temp > 20) {
await changeClothes("warm");
} else {
await changeClothes("cold");
}
await teethPromise;
}
ในตัวอย่างด้านบนสมมติว่ามีการปฏิเสธว่าฟันสัญญา (ข้อผิดพลาด: ออกจากยาสีฟัน!) ก่อนที่จะได้รับอุณหภูมิจริง ในกรณีนี้จะมีการปฏิเสธสัญญาที่ไม่สามารถจัดการได้จนกว่าจะรอฟันสัญญา
ประเด็นของฉันคือ ... หากเราพิจารณาว่าการปฏิเสธคำสัญญาที่ไม่ได้จัดการเป็นปัญหาสัญญาที่ได้รับการจัดการโดยผู้รอภายหลังอาจได้รับรายงานว่าเป็นข้อบกพร่อง จากนั้นอีกครั้งหากเราพิจารณาการปฏิเสธคำสัญญาที่ไม่ได้จัดการเพื่อไม่เป็นปัญหาบั๊กที่ถูกกฎหมายอาจไม่ได้รับการรายงาน
คิดเกี่ยวกับเรื่องนี้?
สิ่งนี้เกี่ยวข้องกับการสนทนาที่พบในโครงการ Node.js ที่นี่:
ค่าเริ่มต้นพฤติกรรมการตรวจจับการปฏิเสธที่ไม่สามารถจัดการได้
ถ้าคุณเขียนรหัสด้วยวิธีนี้:
function getReadyForBed() {
let teethPromise = brushTeeth();
let tempPromise = getRoomTemperature();
// Change clothes based on room temperature
return Promise.resolve(tempPromise)
.then(temp => {
// Assume `changeClothes` also returns a Promise
if (temp > 20) {
return Promise.resolve(changeClothes("warm"));
} else {
return Promise.resolve(changeClothes("cold"));
}
})
.then(teethPromise)
.then(Promise.resolve()); // since the async function returns nothing, ensure it's a resolved promise for `undefined`, unless it's previously rejected
}
เมื่อ getReadyForBed ถูกเรียกใช้มันจะสร้างสัญญาสุดท้าย (ไม่ส่งคืน) พร้อมกันซึ่งจะมีข้อผิดพลาด "ปฏิเสธการจัดการ" แบบเดียวกันกับสัญญาอื่น ๆ (อาจไม่มีอะไรแน่นอนขึ้นอยู่กับเครื่องยนต์) (ฉันคิดว่ามันแปลกมากที่ฟังก์ชั่นของคุณไม่ส่งคืนสิ่งใดซึ่งหมายความว่าฟังก์ชั่น async ของคุณให้คำมั่นว่าจะไม่ได้กำหนด
ถ้าฉันทำสัญญาทันทีโดยไม่ต้องจับและเพิ่มในภายหลังการใช้งาน "ข้อผิดพลาดการปฏิเสธการจัดการ" ส่วนใหญ่จะถอนคำเตือนจริง ๆ เมื่อฉันจัดการในภายหลัง กล่าวอีกนัยหนึ่ง async / คอยไม่เปลี่ยนการสนทนา "ปฏิเสธการจัดการ" ในทางที่ฉันเห็น
เพื่อหลีกเลี่ยงข้อผิดพลาดนี้โปรดเขียนรหัสด้วยวิธีนี้:
async function getReadyForBed() {
let teethPromise = brushTeeth();
let tempPromise = getRoomTemperature();
// Change clothes based on room temperature
var clothesPromise = tempPromise.then(function(temp) {
// Assume `changeClothes` also returns a Promise
if(temp > 20) {
return changeClothes("warm");
} else {
return changeClothes("cold");
}
});
/* Note that clothesPromise resolves to the result of `changeClothes`
due to Promise "chaining" magic. */
// Combine promises and await them both
await Promise.all(teethPromise, clothesPromise);
}
โปรดทราบว่าสิ่งนี้ควรป้องกันการปฏิเสธคำสัญญาที่ไม่สามารถจัดการได้