JavaScript'te Ertelenmiş, Vaat ve Gelecek arasındaki farklar nelerdir?


300

Ertelemeler, Vaatler ve Vadeli İşlemler arasındaki farklar nelerdir?
Bu üçünün arkasında genel olarak onaylanmış bir teori var mı?


11
Bunun jQuery ile ilgisi olduğunu düşünmüyorum ...
BoltClock


8
Onları kendim kullanmadım ama burada wikipedia en.wikipedia.org/wiki/Futures_and_promises üzerinde oldukça iyi bir giriş var . Her ne kadar kullanım durumunu tam olarak anlamıyorum. Javascript gibi zaman uyumsuz bir etkinlikte kullanılan dilde. İlk bakışta, daha temiz bir api dışında, geri aramalar üzerinde neler sunduklarını göremiyorum. Birisi örnek bir kullanım örneği sunabilir ve bu kavramların nasıl uygulandığını ve geri aramaların neden verimsiz bir çözüm olacağını gösterebilirse çok sevinirim. @duri bunun jQuery ile bir ilgisi yok. JQuery etiketi lütfen kaldırılabilir
AshHeskes

2
@ jfriend00 harika bağlantı, muhtemelen bir cevap olarak çalışılmalıdır.
fncomp

@ jfriend00 yeni bağlantı - msdn.microsoft.com/tr-tr/magazine/gg723713.aspx
c69

Yanıtlar:


97

OP'nin sorusuna nasıl cevap vermeye çalıştığımdan hoşlanmıyorum. Gerçek cevap, bir vaat diğer nesnelerle paylaşılan bir şeydir, ertelenmiş bir özel tutulmalıdır. Öncelikle, ertelenen (genellikle Vaat'i uzatan) kendini çözebilir, ancak bir söz bunu yapamayabilir.

Minutiae ile ilgileniyorsanız Promises / A + ' yı inceleyin .


Bildiğim kadarıyla, kapsayıcı amaç, standartlaştırılmış bir arayüz aracılığıyla netliği artırmak ve bağlantıyı gevşetmektir. @ Jfriend00 tarafından önerilen okumaya bakın :

Geri çağrıları işlevlere doğrudan iletmek yerine, sıkıca bağlanmış arabirimlere yol açabilecek bir şey, vaatler kullanarak, senkron veya asenkron kod için endişeleri ayırmaya izin verir.

Şahsen, özellikle eşzamansız istekler tarafından doldurulmuş şablonlar, bağımlılık ağlarına sahip komut dosyaları yükleme ve engelleme olmayan bir şekilde veri oluşturmak için kullanıcı geri bildirimi sağlama gibi ertelenmiş buldum.

Gerçekten, JS modunda CodeMirror'ı eşzamansız olarak yükledikten sonra bir şey yapmanın saf geri arama formunu karşılaştırın (özür dilerim, bir süredir jQuery kullanmadım ):

/* assume getScript has signature like: function (path, callback, context) 
   and listens to onload && onreadystatechange */
$(function () {
   getScript('path/to/CodeMirror', getJSMode);

   // onreadystate is not reliable for callback args.
   function getJSMode() {
       getScript('path/to/CodeMirror/mode/javascript/javascript.js', 
           ourAwesomeScript);
   };

   function ourAwesomeScript() {
       console.log("CodeMirror is awesome, but I'm too impatient.");
   };
});

Formüle edilmiş vaatlere (tekrar, özür dilerim, jQuery'de güncel değilim):

/* Assume getScript returns a promise object */
$(function () {
   $.when(
       getScript('path/to/CodeMirror'),
       getScript('path/to/CodeMirror/mode/javascript/javascript.js')
   ).then(function () {
       console.log("CodeMirror is awesome, but I'm too impatient.");
   });
});

Yarı sahte kod için özür dilerim, ama umarım temel fikri biraz açıklığa kavuşturur. Temel olarak, standartlaştırılmış bir söz vererek, sözün etrafından geçerek daha net bir gruplamaya izin verebilirsiniz.


10
Bu cevap faydalı olsa da, aslında soruyu ele almamaktadır: sözde ertelemeler uygulamaya bağlı olarak gelecek veya vaatlerdir.
awdz9nld

@ MartinKällman Haklısın! Bunu bir süredir tekrar gözden geçirmemiştim ve biraz öğrendim. Aşağıda ayrı bir cevap göndereceğim, ancak insanlar kullanım örneğinden yararlanmış gibi göründüğü için bunu bırakın.
fncomp

@ MartinKällman, yeni bir cevap yazmayı düşündü. Ancak, OP'nin aslında Vaat ve Ertelemelerin ne için olduğunu bilmek istediğini düşünüyorum. Asıl sorunun cevabı, kabaca "ertelemeler kendiliğinden çözülebilir. AFAIK, vaatlerin ve ertelemelerin arkasındaki teori , geri çağrıları düzleştirme tekniği olan [Fonksiyonel Reaktif Programlama | haskell.org/haskellwiki/Functional_Reactive_Programming] ' den geliyor. ."
fncomp

2
Bu tamamen yanlıştır ve örnekleriniz geri aramalarla yapmak kadar kolaydır. Vaatler geri arama toplama ve ayırma ile ilgili değil, senkronizasyon kodu gibi zaman uyumsuz kod yazmak için bir DSL sağlamak. Özellikle fn(callback, errback)daha sıkı bir şekilde bağlanmış veya daha az kullanışlı değil fn().then(callback, errback)- ama yine de vaatleri kullanmanın yanlış bir yolu. Özellikle kargo kült $.whenörneğinden nefret ediyorum - $.whengeri aramalarla çalışan bir işleve sahip olmamanız için hiçbir neden yok .
Esailija

Geri arama cehenneminin ne olduğunu bildiğim +1 olsa da bu soruya cevap vermiyor.
Bhojendra Rauniyar

146

Seçilen cevap dahil bu cevaplar, kavramsal olarak vaat tanıtan, ancak tam olarak farklılıklar (ve onları orada uygulayan kütüphaneleri kullanırken oluşan terminolojisinde ne özelliklerini eksik için iyidir vardır önemli farklılıklar).

Hala gelişen bir özellik olduğundan, cevap şu anda hem referansları ( wikipedia gibi ) hem de uygulamaları ( jQuery gibi) incelemeye çalışmaktan geliyor :

  • Ertelenmiş : Asla popüler referanslarda tarif edilmemiştir, 1 2 3 4 ancak uygulamalarda söz verilen kararın hakemidir (uygulama ve ). 5 6 7 resolvereject

    Bazen ertelemeler de söz verir (uygular then), 5 6 kez daha ertelenmiş olanların yalnızca çözümleme yeteneğine sahip olması ve kullanıcıyı kullanma vaadine erişmeye zorlaması daha saf görülür . 7 then

  • Promise : Tartışılan strateji için en kapsamlı kelime.

    Eşzamanlılığını soyutlamak istediğimiz bir hedef fonksiyonun sonucunu saklayan ve thenbaşka bir hedef fonksiyonu kabul eden ve yeni bir söz veren bir fonksiyonu ortaya koyan bir proxy nesnesi . 2

    CommonJS'den bir örnek :

    > asyncComputeTheAnswerToEverything()
        .then(addTwo)
        .then(printResult);
    44

     

    Sorumluluk çözümüne kimin düştüğü konusunda hiçbir zaman belirtilmemesine rağmen, daima popüler referanslarda açıklanmaktadır. 1 2 3 4

    Her zaman popüler uygulamalarda bulunun ve asla çözünürlük yetenekleri verilmedi. 5 6 7

  • Gelecek : Bazı popüler referanslarda 1 ve en az bir popüler uygulamada bulunan, görünüşte onaylanmamış bir terim , 8, ancak görünüşe göre 'söz' 3 terimini tercih ederek tartışmanın aşamalı olarak kaldırıldığı ve konuyla ilgili popüler tanıtımlarda her zaman belirtilmedi. 9

    Bununla birlikte, en az bir kütüphane terimi, thenişlevselliği sağlamazken eşzamanlılığı ve hata işlemeyi soyutlamak için genel olarak bu terimi kullanır . 10 'Vaat' teriminden kaçınmanın kasıtlı olup olmadığı belirsizdir, ancak vaatler 'kiralanabilirler' etrafında kurulduğundan muhtemelen iyi bir seçimdir. 2

Referanslar

  1. Vaatler ve Vadeli İşlemler hakkında Wikipedia
  2. Vaatler / A + spesifikasyonu
  3. DOM Vaatlerde Standart
  4. DOM Standardı, Özel WIP Vaat Ediyor
  5. DOJO Araç Kiti Ertelenmiş
  6. jQuery Ertelenmiş
  7. S
  8. FutureJS
  9. Vaatler ile ilgili Fonksiyonel Javascript bölümü
  10. AngularJS Entegrasyon Testinde Vadeli İşlemler

Çeşitli potansiyel olarak kafa karıştırıcı şeyler


5
"Gelecek" terimine biraz daha fazla açıklama eklemek için - gelecekler 80'lerin ortalarına kadar uzanan birçok programlama dilinde uzun bir geçmişe sahiptir. Ve terim bugün, özellikle JVM'de hala yaygın olarak kullanılmaktadır. JavaScript, Java'nın "Gelecek" ile kastettiğine benzer bir şey ifade etmek için "Promise" terimini kullanmayı seçmiş görünüyor. Scala, JavaScript programcılarının Promise dediği şeylerin "okuma" ve "yazma" tanıtıcılarını ifade etmek için aynı konsepti "Gelecek" ve "Söz" olarak ayırır.
Heather Miller

1
Ve tabii ki Microsoft bunun için kendi terimlerini bulmak zorundaydı, bu yüzden C # olarak adlandırılırlarTask
BlueRaja - Danny Pflughoeft

72

Gerçekten benim için tıklamayı sağlayan şey Domenic Denicola'nın bu sunumuydu.

Bir github özünde , en çok sevdiğim açıklamayı verdi, çok özlü:

Vaatlerin amacı bize async dünyasında fonksiyonel kompozisyon ve hata köpürmesini geri vermektir.

Diğer bir deyişle, vaatler, sanki senkronize gibi yazmak kadar kolay olan eşzamansız kod yazmamızı sağlayan bir yoldur .

Bu örneği, sözlerle düşünün:

getTweetsFor("domenic") // promise-returning async function
    .then(function (tweets) {
        var shortUrls = parseTweetsForUrls(tweets);
        var mostRecentShortUrl = shortUrls[0];
        return expandUrlUsingTwitterApi(mostRecentShortUrl); // promise-returning async function
    })
    .then(doHttpRequest) // promise-returning async function
    .then(
        function (responseBody) {
            console.log("Most recent link text:", responseBody);
        },
        function (error) {
            console.error("Error with the twitterverse:", error);
        }
    );

Bu senkron kodu yazıyormuşsunuz gibi çalışır:

try {
    var tweets = getTweetsFor("domenic"); // blocking
    var shortUrls = parseTweetsForUrls(tweets);
    var mostRecentShortUrl = shortUrls[0];
    var responseBody = doHttpRequest(expandUrlUsingTwitterApi(mostRecentShortUrl)); // blocking x 2
    console.log("Most recent link text:", responseBody);
} catch (error) {
    console.error("Error with the twitterverse: ", error);
}

(Bu hala karmaşık görünüyorsa, o sunumu izleyin!)

Ertelenmiş ile ilgili olarak, bir yol .resolve()ya da .reject()vaat ediyor. Gelen Sözler / B spec, denir .defer(). JQuery'de$.Deferred() .

Bildiğim kadarıyla, jQuery'deki Promise uygulamasının en azından jQuery 1.8.2 itibariyle bozulduğunu (bu özete bakın) unutmayın.
Sözde uygular vaatler / A sonradan uygular , ancak tüm "async try / catch" işlevselliğinin çalışmadığı anlamında doğru hata işlemeyi almazsınız. Yazık ki, zaman uyumsuz kod ile bir "dene / yakala" sahip olmak tamamen serin.

Promises kullanacaksanız (bunları kendi kodunuzla denemelisiniz!) Kris Kowal'ın Q'sunu . JQuery sürümü, temiz jQuery kodu yazmak için sadece bazı geri çağrı toplayıcıdır, ancak noktayı kaçırır.

Gelecek ile ilgili hiçbir fikrim yok, bunu herhangi bir API'da görmedim.

Edit: Domenic Denicola'nın Youtube sözleri @Farm'dan gelen sözler aşağıda un yorumunu.

Videodan Michael Jackson'dan bir alıntı (evet, Michael Jackson ):

Bu cümleyi aklınızda yakmanızı istiyorum: Bir söz, eşzamansız bir değerdir .

Bu mükemmel bir tanımdır: bir söz gelecekten gelen bir değişken gibidir - bir noktada var olan (veya gerçekleşecek) bir şeye birinci sınıf bir referans.


5
W3 ve Chrome çekirdek ekibinin bir üyesi tarafından Futures'ın (şimdi DOM'da
oligofren

1
@oligofren Bağlantı için teşekkürler, güzel görünüyor! Bu arada, ne gizemli bir sinir bozucu favicon lol.
Camilo Martin

1
Bu cevabın çok daha fazla oyuna ihtiyacı var. Kabul edilen cevap IMO'sundan daha yüksek oy kullanılmalıdır.
Chev

1
Domenic Denicola'nın sözler hakkındaki YouTube konuşması: youtube.com/watch?v=hf1T_AONQJU
Çiftlik

@Çiftlik Harika! Bunu cevaba ekleyeceğim.
Camilo Martin

32

Bir Söz , söz verildiğinde mutlaka bilinmeyen bir değerin proxy'sidir. İşleyicileri, eşzamansız bir eylemin nihai başarı değeri veya başarısızlık nedeniyle ilişkilendirmenize olanak tanır. Bu, eşzamansız yöntemlerin eşzamanlı yöntemler gibi değerleri döndürmesini sağlar: asenkron değer yerine, eşzamansız yöntem gelecekte bir noktada bir değere sahip olma vaadini döndürür.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

deferred.promise()Yöntem zaman uyumsuz bir işlev iç talebin ilerlemesi veya duruma müdahale başka kod önlemek için izin verir. Promise, yalnızca ek işleyiciler eklemek veya durumu belirlemek için gereken Ertelenmiş yöntemleri ortaya çıkarır ( daha sonra, tamamlandı, başarısız oldu, her zaman, boru, ilerleme, durum ve vaat ), ancak durumu değiştirenleri ( çözme, reddetme, bildirme, çözme, rejectWith ile ve bildirWith ).

Hedef sağlanırsa, deferred.promise()yöntemleri ona ekler ve ardından yeni bir tane oluşturmak yerine bu nesneyi döndürür. Bu, Vaat davranışını zaten var olan bir nesneye eklemek için yararlı olabilir.

Bir Erteleme oluşturuyorsanız, bir noktada ertelenebilmesi veya reddedilebilmesi için Ertelenmiş'e bir referans tutun. Diğer kodun geri çağrıları kaydedebilmesi veya geçerli durumu inceleyebilmesi için yalnızca Promise nesnesini deferred.promise () yoluyla döndürün.

Bir Sözün , Ertelenmiş olarak henüz bitmemiş bir işi temsil ettiği yerde henüz bilinmeyen bir değeri temsil ettiğini söyleyebiliriz .


resim açıklamasını buraya girin


1
artı 1 grafik gösterimi için. Bravisimo !! ^ _ ^
Ashok MA

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.