JavaScript ES6 Promises bir çözümün ardından neden yürütülmeye devam ediyor?


105

Anladığım kadarıyla bir söz, çözebilen () veya reddedebilen () bir şeydir, ancak sözdeki kodun bir çözüm veya reddetme çağrıldıktan sonra çalışmaya devam ettiğini öğrenmek beni şaşırttı.

Çözme veya reddetmeyi, tüm anında işlev yürütmeyi durduracak, çıkış veya dönüşün eşzamansız bir sürümü olduğunu düşündüm.

Birisi, aşağıdaki örneğin bir çözümleme çağrısından sonra bazen console.log'u gösterdiğinin arkasındaki düşünceyi açıklayabilir mi?

var call = function() {
    return new Promise(function(resolve, reject) {
        resolve();
        console.log("Doing more stuff, should not be visible after a resolve!");
    });
};

call().then(function() {
    console.log("resolved");
});

jsbin


13
Mantıklı bir soru, ama sonra tekrar, JS sadece sizin söylediğiniz gibi birbiri ardına bir ifadeyi yürütür. resolve()sihirli bir şekilde etkisi olacak bir JS kontrol ifadesi değildir return, sadece bir işlev çağrısıdır ve evet, yürütme ondan sonra devam eder.

Bu iyi bir soru ve tüm yanıtları okuduktan sonra bile en iyi uygulamalardan emin değilim ...
Gabriel Glenn

Bence yanlış anlaşılma, resolus () ile tam olarak sonlandırdığınız şeyden kaynaklanıyor: söz, resolüsyon () 'u çağırmanızdan hemen sonra çözülür, ancak daha önce de söylendiği gibi, bu, sözü sonlandıran işlevin, sözünü sonlandırdığı anlamına gelmez. görevi de, dolayısıyla "normal" bir fesih olana kadar devam eder.
Giuseppe Bertone

Yanıtlar:


154

JavaScript, "sonuna kadar çalıştır" konseptine sahiptir . Bir hata atılmadığı sürece, bir returnifadeye veya sonuna ulaşılana kadar bir işlev yürütülür . İşlevin dışındaki diğer kodlar buna müdahale edemez (yine bir hata atılmadıkça).

İsterseniz resolve()sizin Başlatıcı fonksiyonunu çıkmak için bunu aşağıdaki şekilde başa eklemek zorunda return:

return new Promise(function(resolve, reject) {
    return resolve();
    console.log("Not doing more stuff after a return statement");
});

Merhaba Felix - Bence bu hikayenin sadece bir kısmı - diğer kısmı da bunun resolve()kendisi asenkron bir fonksiyon. Diğer (silinmiş) yanıtta da gördüğümüz gibi, bazı insanlar aramanın resolveherhangi bir geri aramayı hemen çalıştıracağına inanıyor .
Alnitak

3
@Alnitak'ın resolvekendisi zaman uyumsuz değil, tamamen eşzamanlı. Kesinlikle ES6 API kullanmasına rağmen, eşzamanlı veya eşzamansız olup olmadığı gözlemlenemez.
Esailija

2
@Esailija tamam, belki de net değildim. Bazı insanlar, aramanın resolveherhangi bir kayıtlı geri aramanın mevcut arama yığınının bir parçası olacak şekilde derhal başlatılmasına neden olacağına inanıyor . Bu doğru değil, bunun yerine geri aramaları sıraya koyuyor (ve haklısın, eşzamansız değil, ama işini yapıyor ve hemen sona eriyor)
Alnitak

@Alnitak: Ne dediğini anlıyorum. Ben sadece neden console.logbu sırayla ortaya çıkıyor yerine neden gösteriliyor diye yorumladım . Şimdiye kadar, neyin resolveve nasıl vaatlerin, soruyu nasıl yorumladığımla ilgisi yok. Ama tabii ki sözler bağlamında bilmek hala önemlidir. Cevabınızı olumlu oylamamın nedenlerinden biri :)
Felix Kling

9
@Bergi, düzenlemenizde "return resol ()" diyorsunuz; bu alışılmadık görünüyor. Kendimi orada önemli bir şey olmadığına ikna etmek için, belgeleri okudum ve (1) resolüsyonun () herhangi bir sonuç getirmiyor gibi göründüğünü ve (2) başlatma geri aramasının dönüş değerinin kullanılmış gibi görünüyor. "Resolution (); return;" demek daha açık olmaz mıydı? böylelikle bu dikkat dağınıklığından kaçınmak?
Don Hatch

19

resolveBir söz verdiğinizde çağrılacak geri aramaların yine de belirtim tarafından eşzamansız olarak çağrılması gerekir. Bu, eşzamanlı ve eşzamansız eylemlerin bir karışımı için vaatler kullanılırken tutarlı davranış sağlamak içindir.

Bu nedenle resolve, geri aramayı başlattığınızda , geri arama sıraya alınır ve işlev yürütme, resolve()aramayı izleyen herhangi bir kodla hemen devam eder .

Yalnızca JS olay döngüsüne geri kontrol verildiğinde, geri arama kuyruktan kaldırılabilir ve gerçekten çağrılabilir.


1
Geri arama kuyruğu A + Specs'de mi yoksa ES6'da mı belgeleniyor?
thefourtheye

5
@thefourtheye: Olay döngüsü özelliği artık HTML5'in bir parçasıdır . ES6, EnqueueJobtarafından çağrılan dahili bir yöntemi tanımlar .then.
Felix Kling

@thefourtheye: Aslında, ES6 kuyrukları da tanımlıyor gibi görünüyor: people.mozilla.org/~jorendorff/… . Sanırım olay döngüsüyle bir şekilde ilgili.
Felix Kling

@FelixKling bağlantılar için teşekkürler - Bunun nasıl çalıştığını biliyordum, ancak bölüm ve dizeden alıntı yapamadım
Alnitak

2
@FelixKling, mikro görevlerini / makro görevlerini, burada "erteleyen" kısımdır "Çalışan yürütme bağlamı olmadığında ve yürütme bağlam yığını boş olduğunda, ECMAScript uygulaması ilk PendingJob'u bir İş Kuyruğundan kaldırır ve içerdiği bilgileri kullanır içinde bir yürütme bağlamı yaratır ve ilişkili İş soyut işleminin yürütülmesini başlatır. "
Benjamin Gruenbaum
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.