SORU
14 Mayıs 2014, ÇARŞAMBA


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
14 Mayıs 2014, ÇARŞAMBA


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:


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 Gecikme 0 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:

async code highlighted

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 alertler ve console.logs 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.

returning 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


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!

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • cyriak

    cyriak

    29 Mart 2006
  • FrankJavCee

    FrankJavCee

    29 Kasım 2008
  • segtlim

    segtlim

    21 EKİM 2008