ES2017'deki bir özellik olan zaman uyumsuz işlevler , vaatleri (belirli bir zaman uyumsuz kod biçimi) ve await
anahtar kelimeyi kullanarak zaman uyumsuz kodun senkronize görünmesini sağlar . Ayrıca, anahtar kelimenin async
önündeki function
asenkron / bekleme işlevini gösteren anahtar kelimenin altındaki kod örneklerinde de dikkat edin . await
Anahtar kelime ile önceden sabitlenmiş bir işlevde olmadan çalışmaz async
anahtar kelime. Şu anda bunun bir istisnası olmadığından hiçbir üst düzey beklemenin işe yaramayacağı anlamına gelir (üst düzey herhangi bir işlevin dışında beklemek anlamına gelir). Üst düzeyawait
bir teklif olsa da .
ES2017, 27 Haziran 2017'de JavaScript için standart olarak onaylandı (yani sonlandırıldı). Async bekliyor tarayıcınızda zaten çalışıyor olabilir, ancak değilse, babel veya traceur gibi bir javascript transpiler kullanarak işlevselliği kullanmaya devam edebilirsiniz . Chrome 55, zaman uyumsuz işlevler için tam desteğe sahiptir. Bu nedenle, daha yeni bir tarayıcınız varsa aşağıdaki kodu deneyebilirsiniz.
Bkz kangax en es2017 uyumluluk tablosunu tarayıcı uyumluluğu için.
Aşağıda doAsync
, üç saniyelik bir duraklama alan ve başlangıç zamanından sonraki her bir duraklamadan sonraki zaman farkını basan bir zaman uyumsuz bekleme işlevi verilmiştir :
function timeoutPromise (time) {
return new Promise(function (resolve) {
setTimeout(function () {
resolve(Date.now());
}, time)
})
}
function doSomethingAsync () {
return timeoutPromise(1000);
}
async function doAsync () {
var start = Date.now(), time;
console.log(0);
time = await doSomethingAsync();
console.log(time - start);
time = await doSomethingAsync();
console.log(time - start);
time = await doSomethingAsync();
console.log(time - start);
}
doAsync();
Await anahtar sözcüğü bir vaat değerinin önüne yerleştirildiğinde (bu durumda vaat değeri doSomethingAsync işlevi tarafından döndürülen değerdir) await anahtar sözcüğü işlev çağrısının yürütülmesini duraklatır, ancak diğer işlevleri duraklatmaz ve devam eder vaat çözülünceye kadar diğer kodların yürütülmesi. Söz çözüldükten sonra sözün değerini açacaktır ve beklemek ve söz ifadesinin yerine bu kaydırılmamış değerin yerini aldığını düşünebilirsiniz.
Bu nedenle, beklemeleri duraklatmaları beklediğinden, satırın geri kalanını yürütmeden önce bir değeri çözdüğünden, bir dizide beklenen zaman farklılıklarını toplayan ve diziyi basan aşağıdaki örnekteki gibi döngüler ve iç işlev çağrıları için kullanabilirsiniz.
function timeoutPromise (time) {
return new Promise(function (resolve) {
setTimeout(function () {
resolve(Date.now());
}, time)
})
}
function doSomethingAsync () {
return timeoutPromise(1000);
}
// this calls each promise returning function one after the other
async function doAsync () {
var response = [];
var start = Date.now();
// each index is a promise returning function
var promiseFuncs= [doSomethingAsync, doSomethingAsync, doSomethingAsync];
for(var i = 0; i < promiseFuncs.length; ++i) {
var promiseFunc = promiseFuncs[i];
response.push(await promiseFunc() - start);
console.log(response);
}
// do something with response which is an array of values that were from resolved promises.
return response
}
doAsync().then(function (response) {
console.log(response)
})
Async işlevinin kendisi bir söz verir, böylece bunu yukarıda veya başka bir async bekliyor işlevinin içinde yaptığım gibi zincirleme ile bir söz olarak kullanabilirsiniz.
İstekleri aynı anda göndermek isterseniz, yukarıdaki işlev başka bir istek göndermeden önce her yanıtı beklerdi Promise.all kullanabilirsiniz .
// no change
function timeoutPromise (time) {
return new Promise(function (resolve) {
setTimeout(function () {
resolve(Date.now());
}, time)
})
}
// no change
function doSomethingAsync () {
return timeoutPromise(1000);
}
// this function calls the async promise returning functions all at around the same time
async function doAsync () {
var start = Date.now();
// we are now using promise all to await all promises to settle
var responses = await Promise.all([doSomethingAsync(), doSomethingAsync(), doSomethingAsync()]);
return responses.map(x=>x-start);
}
// no change
doAsync().then(function (response) {
console.log(response)
})
Söz muhtemelen reddederse, bir try catch'e sarabilir veya try catch'i atlayabilir ve hatanın async / await fonksiyonlarının catch çağrısına yayılmasına izin verebilirsiniz. Özellikle Node.js'de vaat hatalarını işlenmemeye dikkat etmelisiniz. Aşağıda, hataların nasıl çalıştığını gösteren bazı örnekler verilmiştir.
function timeoutReject (time) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
reject(new Error("OOPS well you got an error at TIMESTAMP: " + Date.now()));
}, time)
})
}
function doErrorAsync () {
return timeoutReject(1000);
}
var log = (...args)=>console.log(...args);
var logErr = (...args)=>console.error(...args);
async function unpropogatedError () {
// promise is not awaited or returned so it does not propogate the error
doErrorAsync();
return "finished unpropogatedError successfully";
}
unpropogatedError().then(log).catch(logErr)
async function handledError () {
var start = Date.now();
try {
console.log((await doErrorAsync()) - start);
console.log("past error");
} catch (e) {
console.log("in catch we handled the error");
}
return "finished handledError successfully";
}
handledError().then(log).catch(logErr)
// example of how error propogates to chained catch method
async function propogatedError () {
var start = Date.now();
var time = await doErrorAsync() - start;
console.log(time - start);
return "finished propogatedError successfully";
}
// this is what prints propogatedError's error.
propogatedError().then(log).catch(logErr)
Gidersen burada yaklaşan ECMAScript sürümleri için bitmiş önerilerini görebilirsiniz.
Sadece ES2015 (ES6) ile kullanılabilen buna bir alternatif, bir jeneratör fonksiyonunu saran özel bir fonksiyon kullanmaktır. Jeneratör işlevleri, await anahtar sözcüğünü çevreleyen bir işlevle çoğaltmak için kullanılabilecek bir verim anahtar sözcüğüne sahiptir. Verim anahtar sözcüğü ve jeneratör işlevi çok daha genel bir amaçtır ve asenkronun beklediği fonksiyondan çok daha fazlasını yapabilir. Eşzamansız bekleyen çoğaltmak için kullanılabilecek bir jeneratör işlevi sarıcı istiyorsanız co.js göz atın . Bu arada ko'nun işlevi async'i beklemek gibi işlevler vaat ediyor. Dürüst olmak gerekirse, bu noktada tarayıcı uyumluluğu hem jeneratör işlevleri hem de zaman uyumsuz işlevler için yaklaşık olarak aynı olsa da, async işlevini beklemek istiyorsanız, Async işlevlerini co.js olmadan kullanmalısınız.
IE dışında tüm önemli tarayıcılarda (Chrome, Safari ve Edge) Async işlevleri (2017 itibariyle) için tarayıcı desteği aslında oldukça iyi.