Neden benim değişken sonra tam ben bir işlev içinde değişiklik olur? - Asenkron kod referans
Aşağıdaki örnekler göz önüne alındığında, neden her durumda outerScopeVar
tanımsız mı?
var outerScopeVar;
var img = document.createElement('img');
img.onload = function() {
outerScopeVar = this.width;
};
img.src = 'lolcat.png';
alert(outerScopeVar);
var outerScopeVar;
setTimeout(function() {
outerScopeVar = 'Hello Asynchronous World!';
}, 0);
alert(outerScopeVar);
// Example using some jQuery
var outerScopeVar;
$.post('loldog', function(response) {
outerScopeVar = response;
});
alert(outerScopeVar);
// Node.js example
var outerScopeVar;
fs.readFile('./catdog.html', function(err, data) {
outerScopeVar = data;
});
console.log(outerScopeVar);
// with promises
var outerScopeVar;
myPromise.then(function (response) {
outerScopeVar = response;
});
console.log(outerScopeVar);
Neden çıktı "" örnekler bu tanımsız mı Geçici çözümler istemiyorum, bilmek istiyorumnedenbu oluyor.
Not:Bunun için meşru bir soruAsynchronicity JavaScript. Bu soruyu artırmak ve daha fazla topluluk tespit edebilir basitleştirilmiş örnekler eklemek için çekinmeyin.
CEVAP
Tek kelime cevap:asynchronicity.
Şeyi düşündük
Bu konu binlerce kez en az bir çift, burada Yığın Taşması olarak yineledi. Dolayısıyla, öncelikle son derece yararlı bazı kaynaklara işaret etmek istiyorum:
@Felix Kling's "How to return the response from an AJAX call". Mükemmel cevabı senkron ve asenkron akar gibi anlatan "kod" bölümü. Yeniden görmek
@Benjamin Gruenbaum de çaba aynı konuyu asynchronicity açıklayan koydu.@Matt Esch's answer to "Get data from fs.readFile" ayrıca asynchronicity son derece basit bir şekilde açıklar.
Eldeki sorunun cevabı
Ortak davranış ilk yazalım. Tüm örneklerde, outerScopeVar
bir iç değiştirilirişlevi. İşlevi net olarak derhal idam değil, ya da bir argüman olarak atanan geçti. Bir diyoruzgeri arama.
Şimdi soru, ne zaman geri çağırdı.
Duruma göre değişir. Hadi bazı ortak davranış tekrar izlemek için deneyin:
img.onload
çağrılabilirbazen gelecektene zaman (ve eğer) resim başarıyla yüklendi.setTimeout
çağrılabilirbazen gelecektegecikme süresi doldu ve zaman aşımıclearTimeout
tarafından iptal olmadı. sonra Gecikme0
kullanırken bile, tüm tarayıcılar en az bir zaman aşımı gecikme kapağı (HTML5 spec 4ms belirtilen). not:- bir WordPress kullanmak
$.post
'nın geri çağrılabilirbazen gelecektene zaman (ve eğer) Ajax isteği başarıyla tamamlandı. - '
fs.readFile
çağrılabilir . Node.js ^em>bazen gelecektedosya başarıyla okuyun veya atılmış bir hata.
Her durumda, çalışabilir hangi bir geri arama varbazen gelecekte. "Gelecekte bir gün" dediğimiz şeyi . bu ^strong>zaman uyumsuz akış.
Zaman uyumsuz yürütme eşzamanlı akışı dışarı itti. O zaman uyumsuz kod olacakaslaçalıştırmak senkron kodu süre yığını yürütülüyor. Bu JavaScript anlamı tek dişli ediliyor.
Daha spesifik olarak, zaman JS motor boşta değil, yürütülen bir yığın (a)senkron kod olur anket için olayları tetiklemiş olabilir zaman uyumsuz geri aramaları (örneğin, zaman aşımı süresi doldu, alınan yanıt network) ve onları yürütmek başka. Bu Event Loop olarak kabul edilir.
Yani, zaman uyumsuz kod elle çizilmiş kırmızı şekilleri vurgulanmış ilgili kod bloklarını kalan tüm zaman uyumlu kod idam sonra yürütme:
Kısacası, geri arama işlevleri eşzamanlı olarak oluşturulan, ancak zaman uyumsuz olarak yürütülür. Sadece idam var, ve bunu yapmak için ne kadar zaman uyumsuz bir fonksiyon icra güvenebilir mi?
Basit, gerçekten. Asenkron fonksiyon yürütme bağlıdır mantığı/adlı bu asenkron fonksiyonu içeriden başlanmalıdır. Sonuç bu noktada kullanılabilir, çünkü örneğin, geri arama işlevi içinde alert
ler ve console.log
s hareket beklenen sonuç çıktı.
Kendi geri çağırma mantığı uygulanması
Genellikle zaman uyumsuz bir işlev sonucu ile daha fazla şeyler yapmak, ya da sonuç asenkron işlevi çağrıldı yere göre, farklı şeyler yapmak gerekir. Hadi biraz daha karmaşık bir örnek mücadele:
var outerScopeVar;
helloCatAsync();
alert(outerScopeVar);
function helloCatAsync() {
setTimeout(function() {
outerScopeVar = 'Nya';
}, Math.random() * 2000);
}
Not:Genel asenkron bir fonksiyon olarak rastgele bir gecikme ile setTimeout
kullanıyorum, aynı örneği, readFile
, onload
Ajax ve başka bir zaman uyumsuz Akış için geçerlidir.
Bu örnek açıkça asenkron işlevini yürütür kadar bekliyor diğer örnekleri gibi aynı sorunu yaşıyor.
Hadi kendimize bir geri arama sistemi uygulama mücadele. İlk olarak, o çirkin kurtulalım bu durumda tamamen işe yaramaz olan outerScopeVar
. Sonra bir işlev bağımsız değişkeni kabul eden bir parametre ekliyoruz, bizim geri arama. Zaman uyumsuz işlem tamamlandığında, bu geri arama sonucu geçen deriz. (Lütfen sipariş açıklamalarda okuma) uygulaması:
// 1. Call helloCatAsync passing a callback function,
// which will be called receiving the result from the async operation
helloCatAsync(function(result) {
// 5. Received the result from the async function,
// now do whatever you want with it:
alert(result);
});
// 2. The "callback" parameter is a reference to the function which
// was passed as argument from the helloCatAsync call
function helloCatAsync(callback) {
// 3. Start async operation:
setTimeout(function() {
// 4. Finished async operation,
// call the callback passing the result as argument
callback('Nya');
}, Math.random() * 2000);
}
Çoğu zaman gerçek kullanım durumunda, DOM API ve kütüphaneler çoğu zaten geri arama işlevselliği (bu demonstrasyon örnek helloCatAsync
uygulaması) bulunur. Sadece geri arama işlevi, geçiş ve senkron akışkan idam edeceğini biliyoruz, ve kod için karşılamak için yeniden yapılandırılması gerekiyor.
De göreceksiniz nedeniyle asenkron doğa, mümkün değildir return
bir değeri, bir zaman uyumsuz akış geri senkron akış nereye geri çağırma oldu tanımlanmış, zaman uyumsuz geri yürütüldüğü zaman sonra senkron kod vardır zaten bitmiş yürütülüyor.
return
ing yerine zaman uyumsuz geri arama gelen bir değeri, geri desen kullanmak, ya da... Sözler olacak.
Vaat ediyor
Vanilla JS ile koyunda callback hell tutmak için yollar vardır, ancak söz popülerliği artıyor ve şu anda ES6 (Promise - MDN) standardize ediliyor.
(A.sözleri k.bir. Vadeli işlem) zaman uyumsuz kod daha doğrusal ve böylece keyifli bir okuma sağlar, ancak tüm işlevleri açıklayan bu soru kapsamı dışındadır. Bunun yerine, ilgi için bu mükemmel kaynakları bırakırım
JavaScript asynchronicity hakkında daha fazla okumak
- The Art of Node - Callbacks zaman uyumsuz kod açıklar ve çok iyi vanilla JS örnekler ile geri aramalar ve kod node.js .
Not:Topluluk Wiki, dolayısıyla en az 100 olan herkes itibar ve düzenlemek artırabilir olarak bu cevabı işaretledim! Lütfen bu cevap geliştirmek için çekinmeyin, ya da eğer isterseniz tamamen yeni bir cevap gönder.
İstediğim için bu soruyu bir kurallı konuya cevap asynchronicity sorunları olan ilgisiz Ajax (How to return the response from an AJAX call?), dolayısıyla bu konuda ihtiyaçlarını yardımcı olmak gibi iyi ve yardımsever olarak mümkün!
Neden benim program tam olarak 8192 el...
Neden stil iOS7 içinde UİTableViewStyl...
Neden bazı fonksiyonlar&;__" ve i...
Angularjs form içinde bir düğmesi sayf...
Nasıl Clojure içinde işlev bağımsız de...