Ertelenmiş geri aramalar nelerdir?


15

Bir işlevi başka bir işleve geçirdiğim bir geri arama fikrini anlıyorum ve bu işlev daha sonra verilen işlevi isteğe bağlı olarak kullanıyor.

Google'ı aradıktan sonra bile ertelenmiş geri çağrıları anlamak için uğraşıyorum.

Birisi basit bir açıklama yapabilir mi lütfen? Ruby'de program yapıyorum, ama aynı zamanda C / C ++ 'ı da biraz biliyorum, ama en önemlisi deneyimli bir montaj dili programcısıydım. Bu yüzden biraz pop-up geri çağrı adresleri yığını gibi merak ediyorum? Ben jquery veya node.js öğrenmek umuyorum ve bu ertelenmiş geri aramalar her ikisi için ayrılmaz görünüyor. Temel iş parçacığı ilkelerini anlıyorum (mutex nesnesi başımı incitiyor olsa da;)


Şunu mu demek istediniz: jQuery Deferrednesneleri Bu Node.js'ye özgü bir şey mi?
bfavaretto

1
Hayır genel olarak demek istiyorum. Ben jquery ve muhtemelen node.js öğrenmek istiyorum rağmen, ertelenmiş bir geri arama aslında ilk ne olduğunu ele almak gerektiğini hissettim. Geri aramalarla ilgili Wikipedia makalesini okudum, ancak ertelenmiş geri çağrıları anlayamadım; bu, onu kullanan bu dillerde yer alacak asenkron işlem paradigmasına özgü görünüyor.


1
Ben onların yerine aksine ertelenmiş geri arama kavramsal fikrini gerçekten soruyorum - bunu daha açık bir şekilde ifade etmediysem özür dilerim. Açıklığa kavuşturmaya çalıştığım fikri ve programlama geçmişimi açıklamak için daha fazla dil örnekleri verdim, böylece insanlar cevabı nasıl oluşturacaklarını bileceklerdi. Şimdiye kadar cevaplar için çok teşekkürler - oraya geliyorum!
tentimes

Tamam bence şimdi millet, hepinize teşekkürler! Cevabı ne şekilde yapacağımı bilmiyorum. Cameron kavramı en basit şekilde açıkladı ve gerçekten peşindeydim, ama diğerleri de içeri girdi ve bilgilerime eklendi. Bu konuda yeni olduğum için cevabı ne şekilde kabul edeceğimi bilmiyorum;)
tentimes

Yanıtlar:


4

Talep üzerine, cevap olarak sunulan yorumlar:


JS'deki işlevlerin birinci sınıf nesneler olduğu ve bu nedenle oluşturuldukları zamandan sonra ihtiyaç duyulana kadar saklanabileceği gerçeğini tamamen bilmediğinizden emin değilim.

Örneğin, bir dosyaya yazmak ve daha sonra bir günlük mesajı yazdırmak istediğinizi varsayalım; böylece "write ()" fonksiyonunu (ya da her neyse) çağırır ve günlük mesajını veren bir fonksiyon iletirsiniz (bu, ertelenmiş geri arama fonksiyonudur). "write ()", verilen işleve bir referansı dahili olarak depolar, dosyaya yazmaya başlar ve yazma işleminin ne zaman tamamlandığını bilmek için kendi geri aramasını ayarlar. Daha sonra yazma işlemi bitmeden geri döner; olduğunda, dahili geri çağrı bir şekilde çağrılır (bu temel çerçevenin işi - node.js durumunda, bir olay döngüsü ile yapılır), bu da daha sonra günlük mesajını yazdıran geri çağrınızı çağırır.

"Ertelenmiş" bölüm, geri arama işlevinizin hemen çağrılmadığı anlamına gelir; çağrılması uygun zamana kadar ertelenir . Node.js dosyasındaki gibi eşzamansız işlevler söz konusu olduğunda, verilen geri arama genellikle işlem tamamlandığında (veya bir hata oluştuğunda) çağrılır.

Çoğu şey node.js'de eşzamansızdır, ancak örneğin jQuery ile tarayıcıda, çoğu şey aslında eşzamanlıdır (açıkça, AJAX istekleri hariç). Birinci sınıf işlevler JavaScript'te çok kullanışlı olduğundan (özellikle büyük kapatma desteği nedeniyle), geri aramalar tarayıcının her yerinde de kullanılır, ancak senkron işlemler için "ertelenmez" (hemen tarafından çağrılmadığı sürece) ancak daha sonra çağırdığınız işlevle).

Temel sistemin olay güdümlü olması, ertelenmiş geri aramaların kullanımı ile dikeydir; her işlem için bir iş parçacığı başlatan ve sonra iş parçasını tamamladığında olayları kullanmadan verilen geri aramayı çağıran bir (çok yavaş) node.js sürümünü hayal edebilirsiniz. Tabii ki, bu korkunç bir model, ama benim açımdan örnek :-)


8

Ertelenmiş geri aramanın çalışma şekli, her geri arama eklediğinizde, bu geri aramanın bir diziye aktarılmasıdır. Sonra, ertelenmiş nesnede .resolve()veya .resolveWith()yöntemi çağrıldığında .done(), dizideki tüm geri çağrılar sırayla yürütülür.

Şimdi Ertelenmiş Bir Nesnenin ne olduğuna bakabiliriz. Örnek olarak aşağıdaki kod parçasını ele alalım.

var deferred = $.Deferred();
var promise = deferred.promise();

Şimdi sahip olduğumuz şey ertelenmiş bir nesne ve ertelenmiş nesnenin vaat nesnesidir. Ertelenmiş bir amacı, ancak söz nesnesi yalnızca yöntemleri vardır, her söz nesne ile aynı yöntemler vardır .done(), .fail()ve .always()her hangi ilgili ertelenmiş nesnesine geri aramalar eklemek için kullanılır event. Ertelenmiş nesnenin diğer birçok yöntemi vardır, en önemlisi .resolve()ve .reject(). Ertelenmiş nesnede bu yöntemler çağrıldığında, tüm geri çağrılar çağrılır. .resolve()patlar .done()ve .always()süre geri aramalar .reject()yöntem çağrıları .fail()ve .always()geri aramalar.

Genellikle ertelenen nesne özel bir kapsam içinde gizli tutulur ve söz verilen nesne, geri çağrıların üzerine yerleştirilebilmesi için işlevden döndürülür. Ertelenmiş nesne daha sonra, örneğin bir ajax isteği tamamlandıktan sonra veya bir görüntü yüklendikten sonra, bir setTimeout, vb. Sonra çözülecektir. Ertelenmiş bir nesnenin yalnızca bir kez çözülebileceğini fark etmek de önemlidir. Zaten çözülmüşse, geri aramalar hemen çağrılacaktır.

İşte benim kullandığım başka bir örnek:

function loadImage(url) {
    var def = $.Deferred(),
        img = new Image();
    $(img).on("load error",function(e){
        if (e.type === "error") {
            def.reject(url);
        }
        else {
            def.resolve(url);
        }
    });
    img.src = url;
    // return the promise object so that callbacks can
    // be defined on the deferred object.
    return def.promise();
}
loadImage("foobar.jpg").done(function(){
    alert("The image is loaded!");
}).fail(function(){
    alert("The image failed to load!");
}).always(function(){
    alert("This is always called!");
});

JQuery $.Deferred()yöntemi ve ertelenmiş nesneler hakkında daha fazla bilgi için http://api.jquery.com/category/deferred-object/ adresini ziyaret edin.


Başımı ertelenmiş geri arama kavramına döndürdüğümde bu muhtemelen paha biçilmez olacaktır. Maalesef, ertelenmiş geri aramanın ne olduğunu anlamadım. Daha arkasındaki kavramsal fikri arıyorum. Mihia'nın fikri boyunca. Bir kez kafamı döndüğümde belki js'i anlayabilirim.
tentimes

3

Emin değilim ama değiştirilmiş bir geri çağrının eşzamansız bir geri çağrıyı ifade ettiğine inanıyorum, bu yüzden bunun için daha iyi şansınız olacak.

Bulduğum en iyi açıklama http://www.nodebeginner.org idi.

Hey, muhtemelenExpensiveFunction (), lütfen eşyalarınızı yapın, ama ben, tek Node.js iş parçacığı, bitinceye kadar burada beklemeyeceğim, aşağıdaki kod satırlarını yürütmeye devam edeceğim, bu yüzden lütfen Bu callbackFunction () burada ve pahalı şeylerinizi bitirdikten sonra çağırın? Teşekkürler!"

Bu örnekte, muhtemelenExpensiveFunction engellemeyen (veya zaman uyumsuz bir işlev). Bu, hemen yürütülmediği, ancak olay döngüsüne yerleştirildiği anlamına gelir. Node.js iş parçacığı yürütmeye devam edecek, ancak bir süre sonra olay döngüsünden bir şey yürütmeye karar verecek. Büyük olasılıkla ExpensiveFunction'a ulaştığında, onu çağırır ve büyük olasılıklaExpensiveFunction yürütmeyi bitirdiğinde, kendisine parametre olarak geçirilen (ertelenmiş) geri aramayı çağırır.

Muhtemelen ExpensiveFunction örneği olarak fs.readFile dosyasını alabilirsiniz


Teşekkürler. Ancak, pahalı işlev zaten geri döndüyse ve işin ana iş parçacığına geri döndüyseniz, bunu nasıl yapacak? Biraz anlamıyorum. Fonksiyon sona erdikten sonra da bir şekilde devam ediyor mu diyorsunuz?

Cevabı düzenledi, belki şimdi daha açık.

Çok yararlı. Ama ... bu saklı geri arama dizisini işlemem gerekiyor mu? Demek istediğim, bu listeyi işleyen nedir? (Örneğin) js, bu geri çağrıları sizinle ilgili hiçbir şey yapmanıza gerek kalmadan arka planda kaldırıyor mu, yoksa bir olayın node.js veya bir şeyin belirli bir geri çağrıyı çağırmasına neden olmasıdır. Üzgünüm, söylediklerinizin yaklaşık% 70'ini alıyorum ama geri kalanında biraz kayboldum :)
tentimes

@tentimes - "bu listeyi işleyen nedir?" $ .Deferred () nesnesi listeyi işliyor. Orijinal ertelenmiş nesneyi çağırdığınızda .resolve()veya .reject()geri çağrıldığında, geri aramaların listesi çağrılır.
user400654

2
@tentimes: Söylediklerinizden, JS'deki işlevlerin birinci sınıf nesneler olduğu ve bu nedenle oluşturuldukları zamandan sonra ihtiyaç duyulana kadar saklanabileceği gerçeğini tamamen bilmediğinizden emin değilim. Örneğin, bir dosyaya yazmak ve daha sonra bir günlük mesajı yazdırmak istediğinizi varsayalım; böylece "write" fonksiyonunu (ya da her neyse) çağırıp günlük mesajını veren bir fonksiyon iletin. "write ()", verilen işleve bir referansı dahili olarak depolar, dosyaya yazmaya başlar ve yazma işleminin ne zaman tamamlandığını bilmek için kendi geri aramasını ayarlar. Daha sonra yazma işlemi bitmeden geri döner; olduğunda fonksiyonunuz çağrılır.
Cameron

3

JavaScript tek iş parçacıklıdır, bu nedenle bunu anlamak için iş parçacıkları açısından düşünemezsiniz. Aşağıda, jQuery kullanarak hem normal hem de eşzamansız geri aramalara bir örnek verilmiştir:

var regularCallback = function(evt) {
    alert("I'm a callback!")
}
var asyncCallback = function(data) {
    alert("I only run when an async operation finishes!")
}

// Bind the regular callback to a button's click event
$('#mybutton').on('click', regularCallback);

// Start an ajax request to the server. The request is asynchronous, so code
// below this line will execute immediately. The callback function
// will only be called when the request is complete.
$.get("http://google.com", asyncCallback);

Şimdi bu beni bir yere götürüyor, teşekkürler. Yani asenkron, ajax ile kurduğum bir olaya yanıt veriyor - bu sadece onu besliyor ve olay gerçekleşirse geri çağrıma çağrılıyor mu? Sanırım anlıyorum. Node.js / jquery, jquery uslig nesnelerine ve onlarla etkileşim kurmak için karmaşık bir sisteme benzer bir şey yapar mı?
tentimes

1
@tentimes, Kesinlikle! Geri aramalar genellikle olaylara yanıt olarak çalışır (ancak "geri arama" bir js dili yapısı olmadığından, bu terim bazen diğer bağlamlarda kullanılır). Kevin'in cevabında gördüğünüz ertelenmiş nesneler (vaatler) temel olarak sözdizimsel şekerdir. Bazı (eşzamansız) bir olay tetiklendiğinde "çözümlenir" veya "reddedilir", ardından uygun geri çağırma işlevini çağırırlar ("tamamlandı" veya "başarısız", sonra "her zaman"). Bunları jQuery'de kullanmak kodu daha okunabilir hale getirebilir ve bazı ek numaralara izin verir (örneğin, bir ajax isteği tetikledikten sonra ikinci bir geri arama eklemek gibi).
bfavaretto

Her ikisi de eşzamansız geri aramalar
Raynos

1

Ertelenmiş geri aramalar (diğer adıyla Promices ), acı ve geri arama spagetti olmadan sıralı asenkron kod yazmanıza olanak tanır:

$.when( doAjax(), doAnotherAjax() ).then( haveFunWithMoreAjax ).then( animateStuff );

'when', işlevlerin paralel olarak dönmesini beklemenizi sağlar ve thensıralı olarak zincirlenebilir.

bir not: jQuery ertelendi ! = Promices / A , sözdizimleri biraz farklı.

Konu hakkında iyi makaleler var: biri IEBlog'da , diğeri bazı rastgele bloglarda , bir kitapta ve popüler bir yığın akışı sorusunda


1
ahh .. ortaya çıkıyor - OP biraz farklı bir şey sordu .. şey, umarım bu cevap belki bir gün başka birine yardım edecek.
c69
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.