Bir fonksiyonun içinde değiştirdikten sonra değişkenim neden değişmiyor? - Asenkron kod referansı


669

Aşağıdaki örnekler göz önüne alındığında, neden outerScopeVarher durumda tanımsız?

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);

// geolocation API
var outerScopeVar;
navigator.geolocation.getCurrentPosition(function (pos) {
    outerScopeVar = pos;
});
console.log(outerScopeVar);

undefinedBu örneklerin hepsinde neden çıktı ? Geçici çözümler istemiyorum, bunun neden olduğunu bilmek istiyorum .


Not: Bu, JavaScript eşzamansızlığı için kanonik bir sorudur . Bu soruyu geliştirmek ve topluluğun tanımlayabileceği daha basitleştirilmiş örnekler eklemek için çekinmeyin.



@Dukeling teşekkürler, bu bağlantıyla yorum yaptığımdan eminim ama görünüşte bazı eksik yorumlar var. Ayrıca, düzenlemenizle ilgili olarak: Bu soru ararken, başka bir soruyu dupe olarak işaretlemek için başlıkta "kanonik" ve "asenkronikliğin" bulunmasına yardımcı olduğuna inanıyorum. Ve elbette, bu eşzamansızlık açıklamaları ararken Google'dan bu soruyu bulmada da yardımcı oluyor.
Fabrício Matté

3
Biraz daha fazla düşününce, "kanonik asenkroniklik konusu" başlığı üzerinde biraz ağır, "asenkron kod referansı" daha basit ve daha nesneldir. Ayrıca çoğu insanın "asenkronlik" yerine "asenkron" aradığına da inanıyorum.
Fabrício Matté

1
Bazı insanlar değişkenlerini işlev çağrısından önce başlatır. Bir şekilde bunu temsil eden unvanı değiştirmeye ne dersiniz? " Bir işlevin içinde değiştirdikten sonra değişkenim neden değişmiyor ?" Gibi. ?
Felix Kling

Yukarıda bahsettiğiniz tüm kod örneklerinde "alert (outerScopeVar);" ŞİMDİ yürütür, "outerScopeVar" değerine atama LATER olur (zaman uyumsuz olarak).
refactor

Yanıtlar:


542

Tek kelimeyle cevap: eşzamansızlık .

Önsözler

Bu konu, Stack Overflow'ta en az birkaç kez yinelenmiştir. Bu nedenle, ilk önce, bazı son derece yararlı kaynakları belirtmek isterim:


Eldeki sorunun cevabı

İlk önce ortak davranışı izleyelim. Tüm örneklerde, outerScopeVarbir fonksiyonun içinde değiştirilir . Bu fonksiyon açıkça hemen çalıştırılmaz, atanır veya bir argüman olarak iletilir. Buna geri çağrı diyoruz .

Şimdi soru şu, ne zaman geri arama denir?

Bu duruma bağlı. Bazı ortak davranışları tekrar izlemeye çalışalım:

  • img.onloadGelecekte bazen görülebilir , (ve eğer) görüntünün başarıyla yüklendiği zaman.
  • setTimeoutgelecekte gecikme süresi dolduktan ve zaman aşımı tarafından iptal edilmedikten sonra aranabilir clearTimeout. Not: 0Gecikme olarak kullanırken bile , tüm tarayıcılarda minimum zaman aşımı gecikme sınırı vardır (HTML5 spesifikasyonunda 4ms olarak belirtilmiştir).
  • jQuery'nin $.postgeri çağrısı , gelecekte Ajax isteğinin başarılı bir şekilde tamamlandığında (ve eğer) gelecekte çağrılabilir .
  • Node.js , gelecekte başarılı bir şekilde okunduğunda veya bir hata atıldığında ileridefs.readFile çağrılabilir .

Her durumda, ileride bir süre geçebilecek olan bir geri çağırma var . Bu "gelecekte bir süre", zaman uyumsuz akış olarak adlandırdığımız şeydir .

Eşzamansız çalıştırma, eşzamanlı akıştan dışarı itilir. Başka bir deyişle, zaman uyumsuz kod, zaman uyumlu kod yığını yürütülürken yürütülmez. JavaScript'in tek iş parçacıklı olmasının anlamı budur.

Daha spesifik olarak, JS motoru rölantide olduğunda - (a) senkron kodunun bir yığınını çalıştırmazken, asenkron geri aramaları tetiklemiş olabilecek olayları (örn; süresi dolmuş zaman aşımı, alınan ağ yanıtı) ardı ardına alır ve bunları birbiri ardına yürütür. Bu Olay Döngüsü olarak kabul edilir .

Yani, elle çizilmiş kırmızı şekillerde vurgulanan asenkron kod, sadece ilgili kod bloklarında kalan tüm senkron kod çalıştırıldıktan sonra çalıştırılabilir:

eşzamansız kod vurgulandı

Kısacası, geri çağırma işlevleri eşzamanlı olarak oluşturulur, ancak eşzamansız olarak yürütülür. Sadece asenkron bir fonksiyonun yürütülmesine güvenip dayanamadığını ve bunun nasıl yapıldığını bilemezsiniz.

Gerçekten basit. Eşzamansız işlev çalıştırmasına bağlı olan mantık, bu eşzamansız fonksiyonun içinden başlatılmalı / çağrılmalıdır. Örneğin, alerts ve console.logs'leri geriçağırım işlevi içinde hareket ettirmek beklenen sonucu verir çünkü sonuç bu noktada kullanılabilir.

Kendi geri arama mantığınızı uygulama

Genellikle, bir eşzamansız fonksiyonun sonucu ile daha fazla şey yapmanız veya eşzamansız fonksiyonun çağrıldığı yere bağlı olarak, sonuç ile farklı şeyler yapmanız gerekir. Biraz daha karmaşık bir örnek ele alalım:

var outerScopeVar;
helloCatAsync();
alert(outerScopeVar);

function helloCatAsync() {
    setTimeout(function() {
        outerScopeVar = 'Nya';
    }, Math.random() * 2000);
}

Not: Ben kullanıyorum setTimeoutgenel asenkron fonksiyonu olarak rastgele bir gecikme ile, aynı örnek Ajax için geçerlidir readFile, onloadve diğer asenkron akışı.

Bu örnek açıkça diğer örneklerle aynı sorundan muzdarip, zaman uyumsuz işlevi yerine getirene kadar beklemiyor.

Kendimize ait bir geri çağırma sistemi uygulayarak başa çıkalım. Öncelikle, outerScopeVarbu durumda tamamen işe yaramaz olan çirkinlerden kurtuluruz . Ardından bir fonksiyon argümanını kabul eden bir parametre ekleriz: Eşzamansız işlem bittiğinde, sonucu geçen bu geri çağrıyı çağırırız. Uygulama (lütfen yorumları sırayla okuyunuz):

// 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);
}

Yukarıdaki örneğin kod pasajı:

// 1. Call helloCatAsync passing a callback function,
//    which will be called receiving the result from the async operation
console.log("1. function called...")
helloCatAsync(function(result) {
    // 5. Received the result from the async function,
    //    now do whatever you want with it:
    console.log("5. result is: ", result);
});

// 2. The "callback" parameter is a reference to the function which
//    was passed as argument from the helloCatAsync call
function helloCatAsync(callback) {
    console.log("2. callback here is the function passed as argument above...")
    // 3. Start async operation:
    setTimeout(function() {
    console.log("3. start async operation...")
    console.log("4. finished async operation, calling the callback, passing the result...")
        // 4. Finished async operation,
        //    call the callback passing the result as argument
        callback('Nya');
    }, Math.random() * 2000);
}

Çoğu zaman gerçek kullanım durumlarında, DOM API ve çoğu kitaplık zaten geri arama işlevini sağlar ( helloCatAsyncbu örnek örnekteki uygulama). Geri arama işlevini geçmeniz ve senkronize akış dışında çalışacağını anlamanız ve kodunuzu buna uyması için yeniden yapılandırmanız yeterlidir.

Ayrıca, eşzamansız yapı nedeniyle return, eşzamansız geri çağırma işlemlerinin senkronizasyon kodunun yürütülmesi tamamlandıktan uzun bir süre sonra yürütüldüğü için eşzamanlı olmayan bir akıştan geri çağrının tanımlandığı eşzamanlı akışa kadar bir değerin imkansız olduğunu fark edeceksiniz .

Yerine returnuyumsuz bir geri çağırma arasında bir değer ing, sen ... Promises geri arama desen yararlanmak varsa, ya da olacaktır.

sözler

Geri arama cehennemini vanilya JS ile birlikte uzak tutmanın yolları olsa da , sözler popülaritesi artıyor ve şu anda ES6'da standartlaştırılıyor (bkz. Promise - MDN ).

Sözler (aka Vadeli İşlemler), asenkron kodun okunmasını daha doğrusal ve dolayısıyla hoş bir şekilde sağlar, ancak tüm işlevlerini açıklamak bu sorunun kapsamı dışındadır. Bunun yerine, bu mükemmel kaynakları ilgilenenlere bırakacağım:


JavaScript eşzamansızlığı hakkında daha fazla okuma materyali

  • Düğüm Sanatı - Geri aramalar, zaman uyumsuz kodu ve geri aramaları vanilla JS örnekleri ve Node.js kodu ile de çok iyi açıklar.

Not: Bu cevabı Community Wiki olarak işaretledim, bu yüzden en az 100 itibarı olan herkes düzenleyebilir ve geliştirebilir! Lütfen bu cevabı geliştirmek için çekinmeyin veya isterseniz tamamen yeni bir cevap gönderin.

Bu soruyu Ajax ile ilgili olmayan eşzamansızlık sorunlarını cevaplamak için kanonik bir konuya dönüştürmek istiyorum (bunun için bir AJAX çağrısından yanıtı nasıl geri alabilirim? ), Bu nedenle bu konunun mümkün olduğunca iyi ve yararlı olması için yardımınıza ihtiyacı var !


1
Son örneğinizde, anonim işlevler kullanmanızın belirli bir nedeni var mı yoksa adlandırılmış işlevler kullanarak aynı şekilde mi çalışıyordu?
JDelage,

1
Kod örnekleri, onu çağırdıktan sonra işlevi bildirirken biraz tuhaf. Kaldırma işlemi nedeniyle çalışır, ancak kasıtlı mıydı?
Bergi

2
kilitlenme mi? felix kling cevabınıza işaret ediyor ve felix cevabına işaret ediyor
Mahi

1
Kırmızı çember kodunun sadece zaman uyumsuz olduğunu anlamalısınız çünkü NATIVE async javascript işlevleri tarafından yürütülüyor. Bu, javascript motorunuzun bir özelliğidir - Node.js veya bir tarayıcı olsun. Asenkrondir, çünkü esasen kara kutu olan bir işleve "geri çağırma" olarak geçirilir (C vb. İle uygulanır). Tüccarsız geliştiriciye, onlar asenkron ... çünkü. Eğer kendi eşzamansız fonksiyonunuzu yazmak istiyorsanız, onu SetTimeout'a (myfunc, 0) göndererek hacklemelisiniz. Bunu yapmalı mısın? Başka bir tartışma .... muhtemelen değil.
Sean Anderson,

@Fabricio "> = 4ms kelepçeyi" tanımlayan spesifikasyonu aradım, ancak bulamadım - MDN'de benzer bir mekanizmadan (iç içe aramaları sıkıştırmak için) bahsettim - developer.mozilla.org/en-US/docs / Web / API /… - HTML özelliklerinin sağ tarafında bir bağlantısı olan var mı?
Sebi

147

Fabrício'nun cevabı çok açık; ancak cevabını daha az teknik olan bir şeyle tamamlamak istedim, bu da asenkroniklik kavramını açıklamaya yardımcı olacak bir analojiye odaklanıyor .


Bir Analoji ...

Dün yaptığım iş bir meslektaşımdan biraz bilgi istedi. Onu çaldım; konuşmanın nasıl geçtiği:

Beni : Bob Merhaba, biz nasıl bilmek gerekir foo 'd bar geçen hafta d'. Jim bunun hakkında bir rapor istiyor ve onunla ilgili ayrıntıları bilen tek kişi sensin.

Bob : Tabii ki, ama 30 dakikaya kadar sürecek mi?

Ben : Bu harika Bob. Bilgiyi aldığında bana bir yüzük ver!

Bu noktada, telefonu kapattım. Raporumu tamamlamak için Bob'dan bilgi almam gerektiğinden, raporu bıraktım ve bir kahve içmeye gittim, sonra bir e-posta aldım. 40 dakika sonra (Bob yavaş), Bob geri aradı ve ihtiyacım olan bilgiyi verdi. Bu noktada, ihtiyacım olan tüm bilgilere sahip olduğum için raporumla çalışmaya devam ettim.


Konuşmanın bunun yerine böyle olup olmadığını düşünün;

Beni : Bob Merhaba, biz nasıl bilmek gerekir foo 'd bar geçen hafta d'. Jim bunun hakkında bir rapor istiyor, ve onun ayrıntılarını bilen tek kişi sensin.

Bob : Tabii ki, ama 30 dakikaya kadar sürecek mi?

Ben : Bu harika Bob. Bekleyeceğim.

Ve orada oturdum ve bekledim. Ve bekledim. Ve bekledim. 40 dakika boyunca. Beklemekten başka bir şey yapmamak. Sonunda Bob bana bilgileri verdi, telefonu kapattık ve raporumu tamamladım. Fakat 40 dakikalık üretkenliği kaybettim.


Bu zaman uyumsuz ve zaman uyumlu davranıştır

Sorumuzdaki tüm örneklerde tam olarak bu oluyor. Bir görüntüyü yüklemek, bir dosyayı diskten yüklemek ve AJAX aracılığıyla bir sayfa istemek tüm yavaş işlemlerdir (modern bilgisayar kullanımı bağlamında).

Bu yavaş işlemlerin tamamlanmasını beklemek yerine , JavaScript yavaş işlem tamamlandığında çalıştırılacak olan bir geri çağırma işlevini kaydetmenizi sağlar. Bu arada, ancak, JavaScript diğer kodu yürütmeye devam edecektir. JavaScript'in yavaş çalışmasının tamamlanmasını beklerken diğer kodu çalıştırması , davranışı eşzamansız hale getirir . JavaScript, başka bir kod yürütmeden önce işlemin tamamlanmasını bekleseydi, bu senkronize bir davranış olurdu .

var outerScopeVar;    
var img = document.createElement('img');

// Here we register the callback function.
img.onload = function() {
    // Code within this function will be executed once the image has loaded.
    outerScopeVar = this.width;
};

// But, while the image is loading, JavaScript continues executing, and
// processes the following lines of JavaScript.
img.src = 'lolcat.png';
alert(outerScopeVar);

Yukarıdaki kodda lolcat.png, bir sloooow işlemi olan JavaScript'i yüklemesini istiyoruz . Geri çağırma işlevi, bu yavaş işlem yapıldıktan sonra yürütülecek, ancak bu arada, JavaScript bir sonraki kod satırını işlemeye devam edecektir; yani alert(outerScopeVar).

Bu yüzden alarmın gösterildiğini görüyoruz undefined; çünkü, alert()görüntü yüklendikten sonra hemen işlenir.

Bizim kodunu çözmek için, yapmamız gereken tüm taşımaktır alert(outerScopeVar)kod içine geri arama işlevi. Bunun bir sonucu olarak, artık outerScopeVarglobal bir değişken olarak tanımlanan değişkene ihtiyacımız yok .

var img = document.createElement('img');

img.onload = function() {
    var localScopeVar = this.width;
    alert(localScopeVar);
};

img.src = 'lolcat.png';

Her zaman bir geri çağırma işlevinin belirtildiğini göreceksiniz, çünkü bazı kodları tanımlamak için JavaScript'in tek * yolu bu ancak daha sonraya kadar çalıştırmamak.

Bu nedenle, tüm örneklerimizde function() { /* Do something */ }geri arama; tüm örnekleri düzeltmek için tek yapmamız gereken, işlemin cevabını gerektiren kodu oraya taşımak!

* Teknik eval()olarak da kullanabilirsiniz , ancak bu amaç için eval()kötü


Arayanı bekletmeye nasıl devam edebilirim?

Şu anda buna benzer bir kodunuz olabilir;

function getWidthOfImage(src) {
    var outerScopeVar;

    var img = document.createElement('img');
    img.onload = function() {
        outerScopeVar = this.width;
    };
    img.src = src;
    return outerScopeVar;
}

var width = getWidthOfImage('lolcat.png');
alert(width);

Ancak şimdi bunun return outerScopeVarhemen gerçekleştiğini biliyoruz ; onloadgeri çağırma işlevi değişkeni güncellemeden önce . Bu getWidthOfImage()iade undefinedve undefineduyarılma yol açar .

Bunu düzeltmek için çağıran fonksiyonun getWidthOfImage()bir geri arama kaydetmesine izin vermemiz, ardından genişliğin uyarısını bu geri arama içinde olacak şekilde hareket ettirmemiz gerekir;

function getWidthOfImage(src, cb) {     
    var img = document.createElement('img');
    img.onload = function() {
        cb(this.width);
    };
    img.src = src;
}

getWidthOfImage('lolcat.png', function (width) {
    alert(width);
});

... önceden olduğu gibi, genel değişkenleri kaldırabildiğimizi unutmayın (bu durumda width).


Ancak, sonuçları farklı bir hesaplamada kullanmak veya bir nesne değişkeninde saklamak istiyorsanız, uyarmak veya konsola göndermek ne kadar yararlı?
Ken Ingram

68

İşte hızlı bir referans arayan insanların yanı sıra vaatler ve zaman uyumsuz / bekleyen bazı örnekler içeren daha kısa cevaplar.

Zaman uyumsuz bir yöntem (bu durumda setTimeout) çağıran ve bir ileti döndüren bir işlev için naif yaklaşımla (işe yaramazsa) başlayın :

function getMessage() {
  var outerScopeVar;
  setTimeout(function() {
    outerScopeVar = 'Hello asynchronous world!';
  }, 0);
  return outerScopeVar;
}
console.log(getMessage());

undefinedBu durumda oturum açıldı çünkü getMessagegeri setTimeoutarama çağrılmadan önce geri dönüyor ve güncelleniyor outerScopeVar.

Bunu çözmenin iki ana yolu geri aramalar ve sözler kullanmak :

Callbacks

Buradaki değişiklik , sonuçları bir kez kullanılabilir olduğunda tekrar arama koduna göndermek için çağrılacak getMessagebir callbackparametreyi kabul etmesidir .

function getMessage(callback) {
  setTimeout(function() {
    callback('Hello asynchronous world!');
  }, 0);
}
getMessage(function(message) {
  console.log(message);
});

sözler

Sözler, geri aramalardan daha esnek bir alternatif sunar; çünkü birden çok zaman uyumsuz işlemi koordine etmek için doğal olarak birleştirilebilirler. Bir Promises / A + standart uygulaması yerel olarak node.js (0.12+) ve mevcut birçok tarayıcıda sağlanır, ancak Bluebird ve Q gibi kütüphanelerde de uygulanır .

function getMessage() {
  return new Promise(function(resolve, reject) {
    setTimeout(function() {
      resolve('Hello asynchronous world!');
    }, 0);
  });
}

getMessage().then(function(message) {
  console.log(message);  
});

jQuery Ertelenmiş

jQuery, Deferreds ile verdiği sözlere benzer bir işlevsellik sağlar.

function getMessage() {
  var deferred = $.Deferred();
  setTimeout(function() {
    deferred.resolve('Hello asynchronous world!');
  }, 0);
  return deferred.promise();
}

getMessage().done(function(message) {
  console.log(message);  
});

zaman uyumsuz / bekliyoruz

JavaScript ortamınız asyncve await(Node.js 7.6+ gibi) desteğini içeriyorsa , sözler içinde asyncişlevler içinde eşzamanlı olarak sözler kullanabilirsiniz :

function getMessage () {
    return new Promise(function(resolve, reject) {
        setTimeout(function() {
            resolve('Hello asynchronous world!');
        }, 0);
    });
}

async function main() {
    let message = await getMessage();
    console.log(message);
}

main();

Sözler konusundaki örneğiniz temelde son birkaç saattir aradığım şey. Örneğiniz güzel ve aynı zamanda Promises açıklıyor. Neden bu başka bir yerde değil övünüyor.
Vincent P

Her şey yolunda, ama ya getMessage () 'ı parametrelerle çağırmanız gerekirse? Yukarıdakileri bu senaryoda nasıl yazardınız?
Chiwda

2
Sadece son geri arama parametresini koymayı @Chiwda: function getMessage(param1, param2, callback) {...}.
JohnnyHK

async/awaitNumuneni deniyorum , ama sorun yaşıyorum. A'yı başlatmak yerine, new Promisebir .Get()arama yapıyorum ve bu nedenle herhangi bir resolve()yönteme erişimim yok . Böylece benim getMessage()sonucum değil, Sözü geri veriyor. Bunun için çalışan bir sözdizimi göstermek için cevabınızı biraz düzenleyebilir misiniz?
InteXX

@InteXX .Get()Arama yapma hakkında ne demek istediğinizi bilmiyorum . Yeni bir soru göndermek için muhtemelen en iyisidir.
JohnnyHK

52

Bariz bir şekilde ifade etmek için, fincan temsil eder outerScopeVar.

Asenkron fonksiyonlar gibi ...

kahve için zaman uyumsuz çağrı


13
Eşzamansız bir işleve sahip olmaya çalışırken, 1 saniyede kahveyi içmeye ve 1 dakika içinde kucağınıza dökülmeye çalışacaktı.
Teepeemm

Açıkça söyleseydi, sorunun sorulacağını sanmıyorum, hayır?
broccoli2000

2
@ broccoli2000 Bununla, sorunun açık olduğu kastetmedim, ama bardağın çizimde neyi temsil ettiği belliydi :)
Johannes Fahrenkrug

13

Diğer cevaplar mükemmel ve bu konuda doğrudan açık bir cevap vermek istiyorum. Sadece jQuery asenkron aramaları sınırlandırmak

Tüm ajax çağrıları ( $.getveya $.postveya dahil $.ajax) eşzamansızdır.

Örneğinizi dikkate alarak

var outerScopeVar;  //line 1
$.post('loldog', function(response) {  //line 2
    outerScopeVar = response;
});
alert(outerScopeVar);  //line 3

Kod yürütme satır 1'den başlar, değişken ve tetikleyicileri ve satır 2'deki (yani, gönderim isteğini) eşzamansız aramayı bildirir ve gönderim isteğinin yürütmesini tamamlamalarını beklemeden, satır 3'ten yürütmeye devam eder.

Diyelim ki gönderim isteğinin tamamlanması 10 saniye sürüyor, değeri outerScopeVaryalnızca bu 10 saniyeden sonra ayarlanacak.

Denemek için,

var outerScopeVar; //line 1
$.post('loldog', function(response) {  //line 2, takes 10 seconds to complete
    outerScopeVar = response;
});
alert("Lets wait for some time here! Waiting is fun");  //line 3
alert(outerScopeVar);  //line 4

Şimdi bunu yaptığınızda, 3. satırda bir uyarı alırsınız. Şimdi, gönderi isteğinin bir değer döndürdüğünden emin olana kadar bir süre bekleyin. Sonra Tamam'ı tıklattığınızda, uyarı kutusunda bir sonraki uyarı beklenen değeri yazdırır, çünkü siz beklediniz.

Gerçek hayat senaryosunda kod,

var outerScopeVar;
$.post('loldog', function(response) {
    outerScopeVar = response;
    alert(outerScopeVar);
});

Eşzamansız çağrılara bağlı olan tüm kod, eşzamansız bloğun içine taşınır veya eşzamansız çağrılar beklenir.


or by waiting on the asynchronous callsbiri bunu nasıl yapar?
InteXX

@InteXX Bir geri çağırma yöntemi kullanarak
Teja

Hızlı bir sözdizimi örneğiniz var mı?
InteXX

10

Tüm bu senaryolarda outerScopeVar, asenkron olarak veya daha sonraki bir zamanda gerçekleşen (bazı olayların gerçekleşmesini beklemek veya dinlemek) meydana gelen bir değer değiştirilir veya atanır , bunun için geçerli yürütmenin beklemeyeceği durumlar.outerScopeVar = undefined

Her örneği tartışalım (Asenkron olarak adlandırılan veya bazı olayların gerçekleşmesi için geciken kısmı işaretledim):

1.

görüntü tanımını buraya girin

Burada, o olay üzerine yürütülecek bir olay listesini kaydettik. Görüntünün yüklenmesi. Mevcut çalıştırma sonraki satırlarla sürekli img.src = 'lolcat.png';ve alert(outerScopeVar);bu arada olay gerçekleşmeyebilir. yani, funtion img.onload, belirtilen görüntünün asenkron şekilde yüklenmesini bekler. Bu, şu örneklerin hepsinde olacak - olay farklı olabilir.

2.

2

Burada timeout olayı, belirtilen zamandan sonra işleyiciyi çağıracak rolü oynar. Burada 0, ancak yine de Event Queue, garantili gecikmeyi sağlayan forution işleminin son konumuna ekleneceği asenkron bir olayı kaydeder .

3.

görüntü tanımını buraya girin Bu sefer geri arama ajax.

4.

görüntü tanımını buraya girin

Düğüm, eşzamansız kodlamanın bir kralı olarak düşünülebilir. İşaretli işlev, belirtilen dosyayı okuduktan sonra yürütülecek bir geri çağırma işleyicisi olarak kaydedilir.

5.

görüntü tanımını buraya girin

Açık bir söz (gelecekte bir şeyler yapılacak) asenkronizedir. bkz . JavaScript'teki Ertelenen, Söz ve Gelecek arasındaki farklar nelerdir?

https://www.quora.com/Whats-the-difference-between-a-promise-and-a-callback-in-Javascript

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.