สัญญามีสถานะพวกเขาเริ่มเป็นรอดำเนินการและสามารถชำระให้กับ:
- เติมเต็มความหมายว่าการคำนวณเสร็จสมบูรณ์แล้ว
- ปฏิเสธหมายความว่าการคำนวณล้มเหลว
ฟังก์ชั่นส่งคืนที่สัญญาไว้ไม่ควรทิ้งแต่ควรส่งคืนการปฏิเสธแทน โยนจากสัญญาฟังก์ชั่นที่กลับมาจะบังคับให้คุณใช้ทั้งสอง} catch {
และ .catch
ผู้ที่ใช้ API ที่ได้รับการรับรองไม่คาดว่าจะเกิดสัญญา หากคุณไม่แน่ใจว่า API ของ async ทำงานอย่างไรใน JS - โปรดดูคำตอบนี้ก่อน
1. โหลด DOM หรือเหตุการณ์ครั้งเดียวอื่น ๆ :
ดังนั้นการสร้างสัญญาโดยทั่วไปหมายถึงการระบุเมื่อพวกเขาชำระ - นั่นหมายถึงเมื่อพวกเขาย้ายไปยังเฟสที่ถูกเติมเต็มหรือถูกปฏิเสธเพื่อระบุว่ามีข้อมูล (และสามารถเข้าถึงได้ด้วย.then
)
ด้วยการใช้งานสัญญาที่ทันสมัยที่สนับสนุนPromise
นวกรรมิกเช่น ES6 ดั้งเดิม:
function load() {
return new Promise(function(resolve, reject) {
window.onload = resolve;
});
}
จากนั้นคุณจะใช้สัญญาที่เป็นผลลัพธ์ดังนี้:
load().then(function() {
// Do things after onload
});
ด้วยไลบรารี่ที่รองรับการเลื่อนเวลา (ลองใช้ $ q สำหรับตัวอย่างนี้ที่นี่ แต่เราจะใช้ jQuery ในภายหลัง):
function load() {
var d = $q.defer();
window.onload = function() { d.resolve(); };
return d.promise;
}
หรือด้วย jQuery เช่น API การเชื่อมโยงเหตุการณ์ที่เกิดขึ้นหนึ่งครั้ง:
function done() {
var d = $.Deferred();
$("#myObject").once("click",function() {
d.resolve();
});
return d.promise();
}
2. โทรกลับธรรมดา:
API เหล่านี้ค่อนข้างใช้กันทั่วไปเนื่องจาก ... การเรียกกลับเป็นเรื่องปกติใน JS ลองดูกรณีทั่วไปของการมีonSuccess
และonFail
:
function getUserData(userId, onLoad, onFail) { …
ด้วยการใช้งานสัญญาที่ทันสมัยที่สนับสนุนPromise
นวกรรมิกเช่น ES6 ดั้งเดิม:
function getUserDataAsync(userId) {
return new Promise(function(resolve, reject) {
getUserData(userId, resolve, reject);
});
}
ด้วยไลบรารี่ที่รองรับการเลื่อนเวลา (ลองใช้ jQuery สำหรับตัวอย่างนี้ที่นี่ แต่เราใช้ $ q ด้านบนด้วย):
function getUserDataAsync(userId) {
var d = $.Deferred();
getUserData(userId, function(res){ d.resolve(res); }, function(err){ d.reject(err); });
return d.promise();
}
jQuery ยังเสนอ$.Deferred(fn)
รูปแบบซึ่งมีข้อดีของการอนุญาตให้เราเขียนนิพจน์ที่เลียนnew Promise(fn)
แบบฟอร์มอย่างใกล้ชิดดังนี้:
function getUserDataAsync(userId) {
return $.Deferred(function(dfrd) {
getUserData(userId, dfrd.resolve, dfrd.reject);
}).promise();
}
หมายเหตุ: ที่นี่เราใช้ประโยชน์จากข้อเท็จจริงที่ว่า jQuery deferred resolve
และreject
เมธอดเป็น "detachable"; กล่าวคือ พวกเขาถูกผูกไว้กับอินสแตนซ์ของ jQuery.Deferred () ไม่ใช่ libs ทั้งหมดที่เสนอคุณสมบัตินี้
3. การเรียกกลับสไตล์โหนด ("nodeback"):
ลักษณะการเรียกกลับของโหนด (nodebacks) มีรูปแบบเฉพาะที่การเรียกกลับเป็นอาร์กิวเมนต์สุดท้ายเสมอและพารามิเตอร์แรกเป็นข้อผิดพลาด ให้เรามาแนะนำคนด้วยตนเองก่อน:
getStuff("dataParam", function(err, data) { …
ถึง:
function getStuffAsync(param) {
return new Promise(function(resolve, reject) {
getStuff(param, function(err, data) {
if (err !== null) reject(err);
else resolve(data);
});
});
}
ด้วยการรอการตัดบัญชีคุณสามารถทำสิ่งต่อไปนี้ (ลองใช้ Q สำหรับตัวอย่างนี้ถึงแม้ว่าตอนนี้ Q จะรองรับไวยากรณ์ใหม่ที่คุณควรจะชอบ ):
function getStuffAsync(param) {
var d = Q.defer();
getStuff(param, function(err, data) {
if (err !== null) d.reject(err);
else d.resolve(data);
});
return d.promise;
}
โดยทั่วไปคุณไม่ควรแนะนำสิ่งต่าง ๆ ด้วยตนเองมากเกินไปห้องสมุดสัญญาที่ได้รับการออกแบบโดยคำนึงถึง Node เช่นเดียวกับสัญญาดั้งเดิมใน Node 8+ มีวิธีการสร้างโหนดที่มีอยู่ในตัว ตัวอย่างเช่น
var getStuffAsync = Promise.promisify(getStuff); // Bluebird
var getStuffAsync = Q.denodeify(getStuff); // Q
var getStuffAsync = util.promisify(getStuff); // Native promises, node only
4. ไลบรารีทั้งหมดที่มีการเรียกกลับสไตล์โหนด:
ไม่มีกฎทองคำที่นี่คุณแนะนำพวกเขาทีละคน อย่างไรก็ตามการใช้งานสัญญาบางอย่างอนุญาตให้คุณทำสิ่งนี้เป็นจำนวนมากตัวอย่างเช่นใน Bluebird การแปลง nodeback API เป็น API สัญญาเป็นเรื่องง่ายเพียง:
Promise.promisifyAll(API);
หรือด้วยสัญญาพื้นเมืองในโหนด :
const { promisify } = require('util');
const promiseAPI = Object.entries(API).map(([key, v]) => ({key, fn: promisify(v)}))
.reduce((o, p) => Object.assign(o, {[p.key]: p.fn}), {});
หมายเหตุ:
- แน่นอนเมื่อคุณอยู่ในผู้
.then
ดูแลคุณไม่จำเป็นต้องแนะนำสิ่งต่าง ๆ การส่งคืนสัญญาจาก.then
ผู้จัดการจะแก้ไขหรือปฏิเสธด้วยมูลค่าของสัญญานั้น การขว้างจากผู้.then
ดูแลก็เป็นแนวปฏิบัติที่ดีและจะปฏิเสธสัญญา - นี่คือสัญญาการโยนที่ปลอดภัย
- ในความเป็นจริง
onload
ในกรณีนี้คุณควรใช้มากกว่าaddEventListener
onX