มันยุติธรรมที่จะบอกว่าสัญญาเป็นเพียงน้ำตาลประโยค ทุกสิ่งที่คุณสามารถทำได้ด้วยสัญญาที่คุณสามารถทำได้กับการโทรกลับ ในความเป็นจริงการใช้งานสัญญาส่วนใหญ่ให้วิธีการแปลงระหว่างทั้งสองเมื่อใดก็ตามที่คุณต้องการ
เหตุผลลึก ๆ ว่าทำไมสัญญามักจะดีกว่าที่พวกเขากำลังมากขึ้นcomposeableซึ่งประมาณหมายความว่าการรวมหลายสัญญา "เพิ่งทำงาน" ในขณะที่รวมเรียกกลับหลายมักจะไม่ ตัวอย่างเช่นมันไม่สำคัญที่จะกำหนดสัญญาให้กับตัวแปรและแนบตัวจัดการเพิ่มเติมไปไว้ในภายหลังหรือแม้กระทั่งแนบตัวจัดการกับกลุ่มสัญญาจำนวนมากที่ได้รับการดำเนินการหลังจากแก้ไขสัญญาทั้งหมดแล้วเท่านั้น ในขณะที่คุณสามารถเลียนแบบสิ่งเหล่านี้ด้วยการเรียกกลับต้องใช้รหัสมากขึ้นเป็นเรื่องยากมากที่จะทำอย่างถูกต้องและผลลัพธ์สุดท้ายมักจะบำรุงรักษาได้น้อยกว่ามาก
หนึ่งในวิธีที่ใหญ่ที่สุด (และย่อย) เพื่อให้ได้รับความสามารถในการแต่งเพลงของพวกเขาคือการจัดการค่าตอบแทนและการยกเว้นที่ไม่ได้ตรวจสอบอย่างสม่ำเสมอ ด้วยการเรียกกลับวิธีการจัดการข้อยกเว้นอาจขึ้นอยู่กับการเรียกกลับที่ซ้อนกันหลาย ๆ ครั้งและฟังก์ชันใดที่การเรียกกลับมีการลอง / จับในการนำไปใช้ สัญญากับคุณรู้ว่าข้อยกเว้นซึ่งหนีออกมาทำงานกลับหนึ่งจะถูกจับและส่งผ่านไปยังจัดการข้อผิดพลาดที่คุณให้กับหรือ.error()
.catch()
สำหรับตัวอย่างที่คุณได้รับจากการติดต่อกลับครั้งเดียวเมื่อเทียบกับคำสัญญาเดียวมันเป็นความจริงที่ไม่มีความแตกต่างอย่างมีนัยสำคัญ มันคือเมื่อคุณมีการโทรกลับเป็น zillion กับ zillion สัญญาว่ารหัสตามสัญญามีแนวโน้มที่จะดูดีกว่ามาก
ต่อไปนี้เป็นความพยายามที่บางข้อสมมุติที่เขียนด้วยคำสัญญาและด้วยการเรียกกลับที่ควรจะซับซ้อนพอที่จะทำให้คุณมีความคิดในสิ่งที่ฉันกำลังพูดถึง
ด้วยสัญญา:
createViewFilePage(fileDescriptor) {
getCurrentUser().then(function(user) {
return isUserAuthorizedFor(user.id, VIEW_RESOURCE, fileDescriptor.id);
}).then(function(isAuthorized) {
if(!isAuthorized) {
throw new Error('User not authorized to view this resource.'); // gets handled by the catch() at the end
}
return Promise.all([
loadUserFile(fileDescriptor.id),
getFileDownloadCount(fileDescriptor.id),
getCommentsOnFile(fileDescriptor.id),
]);
}).then(function(fileData) {
var fileContents = fileData[0];
var fileDownloads = fileData[1];
var fileComments = fileData[2];
fileTextAreaWidget.text = fileContents.toString();
commentsTextAreaWidget.text = fileComments.map(function(c) { return c.toString(); }).join('\n');
downloadCounter.value = fileDownloads;
if(fileDownloads > 100 || fileComments.length > 10) {
hotnessIndicator.visible = true;
}
}).catch(showAndLogErrorMessage);
}
ด้วยการโทรกลับ:
createViewFilePage(fileDescriptor) {
setupWidgets(fileContents, fileDownloads, fileComments) {
fileTextAreaWidget.text = fileContents.toString();
commentsTextAreaWidget.text = fileComments.map(function(c) { return c.toString(); }).join('\n');
downloadCounter.value = fileDownloads;
if(fileDownloads > 100 || fileComments.length > 10) {
hotnessIndicator.visible = true;
}
}
getCurrentUser(function(error, user) {
if(error) { showAndLogErrorMessage(error); return; }
isUserAuthorizedFor(user.id, VIEW_RESOURCE, fileDescriptor.id, function(error, isAuthorized) {
if(error) { showAndLogErrorMessage(error); return; }
if(!isAuthorized) {
throw new Error('User not authorized to view this resource.'); // gets silently ignored, maybe?
}
var fileContents, fileDownloads, fileComments;
loadUserFile(fileDescriptor.id, function(error, result) {
if(error) { showAndLogErrorMessage(error); return; }
fileContents = result;
if(!!fileContents && !!fileDownloads && !!fileComments) {
setupWidgets(fileContents, fileDownloads, fileComments);
}
});
getFileDownloadCount(fileDescriptor.id, function(error, result) {
if(error) { showAndLogErrorMessage(error); return; }
fileDownloads = result;
if(!!fileContents && !!fileDownloads && !!fileComments) {
setupWidgets(fileContents, fileDownloads, fileComments);
}
});
getCommentsOnFile(fileDescriptor.id, function(error, result) {
if(error) { showAndLogErrorMessage(error); return; }
fileComments = result;
if(!!fileContents && !!fileDownloads && !!fileComments) {
setupWidgets(fileContents, fileDownloads, fileComments);
}
});
});
});
}
อาจมีวิธีที่ชาญฉลาดในการลดความซ้ำซ้อนของรหัสในเวอร์ชันที่เรียกกลับมาโดยไม่ต้องสัญญา แต่ทุกอย่างที่ฉันคิดได้ว่าจะนำไปใช้ในการดำเนินการตามที่สัญญาไว้