Güncelleme (2017)
Burada 2017'de, Promises JavaScript'te yerleşiktir, ES2015 spesifikasyonu tarafından eklenmiştir (çoklu dolgular, IE8-IE11 gibi eski ortamlar için mevcuttur). Birlikte gittikleri sözdizimi Promise
, Promise
yapıcıya ( yürütücü ) ilettiğiniz ve sözün bağımsız değişken olarak çözümlenmesi / reddedilmesi için işlevleri alan bir geri aramayı kullanır .
Öncelikle, async
artık JavaScript'te bir anlamı olduğundan (belirli bağlamlarda yalnızca bir anahtar kelime olsa da), later
karışıklığı önlemek için işlevin adı olarak kullanacağım .
Temel Gecikme
Yerel vaatler (veya sadık bir çoklu doldurma) kullanmak şöyle görünür:
function later(delay) {
return new Promise(function(resolve) {
setTimeout(resolve, delay);
});
}
Bunun bir versiyonu varsayar Not setTimeout
bununla uyumlu olduğunu tarayıcılar için tanım nerede setTimeout
bu tarayıcı olmayan ortamlarda doğru olmayabilir (aradan sonra bunları vermedikçe geri arama için herhangi bir bağımsız değişken geçmez ve eskiden yoktu Firefox'ta doğru, ancak şimdi; Chrome'da ve hatta IE8'de doğrudur).
Değerli Temel Gecikme
İşlevinizin isteğe bağlı olarak setTimeout
, gecikmeden sonra ekstra argümanlar vermenize izin veren ve daha sonra bunları çağrıldığında geri aramaya aktaran herhangi bir belirsiz modern tarayıcıda bir çözünürlük değeri iletmesini istiyorsanız , bunu yapabilirsiniz (mevcut Firefox ve Chrome; IE11 + , muhtemelen Edge; IE8 veya IE9 değil , IE10 hakkında hiçbir fikrim yok):
function later(delay, value) {
return new Promise(function(resolve) {
setTimeout(resolve, delay, value);
});
}
ES2015 + ok işlevlerini kullanıyorsanız, bu daha kısa olabilir:
function later(delay, value) {
return new Promise(resolve => setTimeout(resolve, delay, value));
}
ya da
const later = (delay, value) =>
new Promise(resolve => setTimeout(resolve, delay, value));
Değerli İptal Edilebilir Gecikme
Zaman aşımını iptal etmeyi mümkün kılmak istiyorsanız, sözünü geri later
veremezsiniz çünkü sözler iptal edilemez.
Ancak, bir cancel
yöntem ve erişimci içeren bir nesneyi söz için kolayca iade edebilir ve iptal etme sözünü reddedebiliriz:
const later = (delay, value) => {
let timer = 0;
let reject = null;
const promise = new Promise((resolve, _reject) => {
reject = _reject;
timer = setTimeout(resolve, delay, value);
});
return {
get promise() { return promise; },
cancel() {
if (timer) {
clearTimeout(timer);
timer = 0;
reject();
reject = null;
}
}
};
};
Canlı Örnek:
const later = (delay, value) => {
let timer = 0;
let reject = null;
const promise = new Promise((resolve, _reject) => {
reject = _reject;
timer = setTimeout(resolve, delay, value);
});
return {
get promise() { return promise; },
cancel() {
if (timer) {
clearTimeout(timer);
timer = 0;
reject();
reject = null;
}
}
};
};
const l1 = later(100, "l1");
l1.promise
.then(msg => { console.log(msg); })
.catch(() => { console.log("l1 cancelled"); });
const l2 = later(200, "l2");
l2.promise
.then(msg => { console.log(msg); })
.catch(() => { console.log("l2 cancelled"); });
setTimeout(() => {
l2.cancel();
}, 150);
2014 Tarafından Verilen Orijinal Cevap
Genellikle bir söz kitaplığınız olur (birini kendiniz yazarsınız veya oradaki birkaç kitaptan biri). Bu kitaplık genellikle oluşturabileceğiniz ve daha sonra "çözebileceğiniz" bir nesneye sahip olacak ve bu nesnenin ondan alabileceğiniz bir "sözü" olacaktır.
O zaman later
şuna benzer bir şeye bakma eğilimindedir:
function later() {
var p = new PromiseThingy();
setTimeout(function() {
p.resolve();
}, 2000);
return p.promise();
}
Soruya bir yorumda sordum:
Kendi söz kitaplığınızı oluşturmaya mı çalışıyorsunuz?
ve sen dedin
Değildim ama sanırım şimdi anlamaya çalıştığım şey buydu. Bir kütüphane bunu nasıl yapardı
Bu anlayışa yardımcı olmak için işte çok basit bir örnek, uzaktan Promises-A uyumlu olmayan: Canlı Kopya
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Very basic promises</title>
</head>
<body>
<script>
(function() {
var PromiseThingy = (function() {
function triggerCallback(callback, promise) {
try {
callback(promise.resolvedValue);
}
catch (e) {
}
}
function Promise() {
this.callbacks = [];
}
Promise.prototype.then = function(callback) {
var thispromise = this;
if (!this.resolved) {
this.callbacks.push(callback);
}
else {
setTimeout(function() {
triggerCallback(callback, thispromise);
}, 0);
}
return this;
};
function PromiseThingy() {
this.p = new Promise();
}
PromiseThingy.prototype.resolve = function(value) {
var n;
if (!this.p.resolved) {
this.p.resolved = true;
this.p.resolvedValue = value;
for (n = 0; n < this.p.callbacks.length; ++n) {
triggerCallback(this.p.callbacks[n], this.p);
}
}
};
PromiseThingy.prototype.promise = function() {
return this.p;
};
return PromiseThingy;
})();
function later() {
var p = new PromiseThingy();
setTimeout(function() {
p.resolve();
}, 2000);
return p.promise();
}
display("Start " + Date.now());
later().then(function() {
display("Done1 " + Date.now());
}).then(function() {
display("Done2 " + Date.now());
});
function display(msg) {
var p = document.createElement('p');
p.innerHTML = String(msg);
document.body.appendChild(p);
}
})();
</script>
</body>
</html>