JavaScript'te then () işlevi ne anlama gelir?


Yanıtlar:


348

JavaScript'te eşzamansız çağrılarla başa çıkmanın geleneksel yolu geri aramalardır. Uygulamamızı kurmak için sunucuya birbiri ardına üç çağrı yapmamız gerektiğini varsayalım. Geri aramalarda, kod aşağıdaki gibi görünebilir (sunucu çağrısı yapmak için bir xhrGET işlevi varsayarak):

// Fetch some server configuration
    xhrGET('/api/server-config', function(config) {
        // Fetch the user information, if he's logged in
        xhrGET('/api/' + config.USER_END_POINT, function(user) {
            // Fetch the items for the user
            xhrGET('/api/' + user.id + '/items', function(items) {
                // Actually display the items here
            });
        });
    });

Bu örnekte, önce sunucu yapılandırmasını getiriyoruz. Daha sonra buna dayanarak, geçerli kullanıcı hakkında bilgi alırız ve son olarak geçerli kullanıcı için öğe listesini alırız. Her xhrGET çağrısı, sunucu yanıt verdiğinde yürütülen bir geri arama işlevi alır.

Şimdi tabii ki ne kadar fazla yuvalama düzeyimiz varsa, kod okumak, hata ayıklamak, korumak, yükseltmek ve temelde çalışmak o kadar zorlaşır. Bu genellikle geri arama cehennemi olarak bilinir. Ayrıca, hataları ele almamız gerekiyorsa, bir hata durumunda ne yapması gerektiğini söylemek için her bir xhrGET çağrısına muhtemelen başka bir işlev iletmemiz gerekir. Tek bir ortak hata işleyicimiz olmasını isteseydik, bu mümkün değil.

Promise API'sı bu yuvalama sorununu ve hata işleme sorununu çözmek için tasarlanmıştır.

Promise API'sı aşağıdakileri önerir:

  1. Her eşzamansız görev bir promisenesne döndürür .
  2. Her promisenesnenin thenbir success işleyici ve bir errorişleyici olmak üzere iki argüman alabilen bir işlevi olacaktır .
  3. İşlevdeki başarı veya hata işleyici , eşzamansız görev tamamlandıktan sonra thenyalnızca bir kez çağrılacaktır .
  4. thenFonksiyon aynı zamanda bir döner promisebirden fazla görüşme zincirleme izin vermek.
  5. Her işleyici (başarı veya hata) , s zincirinde valuebir sonraki işleve a olarak geçecek olan a değerini döndürebilir .argumentpromise
  6. Bir işleyici bir promise(başka bir eşzamansız istek yaparsa) döndürürse , sonraki işleyici (başarı veya hata) yalnızca bu istek tamamlandıktan sonra çağrılır.

Dolayısıyla, önceki örnek kod vaatleri ve $httphizmeti (AngularJs'de) kullanarak aşağıdaki gibi bir şeye dönüşebilir:

$http.get('/api/server-config').then(
    function(configResponse) {
        return $http.get('/api/' + configResponse.data.USER_END_POINT);
    }
).then(
    function(userResponse) {
        return $http.get('/api/' + userResponse.data.id + '/items');
    }
).then(
    function(itemResponse) {
        // Display items here
    }, 
    function(error) {
        // Common error handling
    }
);

Başarıyı ve Hatayı Yaymak

Zincirleme vaatler, bir hizmetin bir sunucu çağrısı yapması, verilerin bazı son işlemlerini yapması ve ardından işlenen verileri denetleyiciye geri döndürmesi gibi birçok işlevselliği gerçekleştirmemizi sağlayan çok güçlü bir tekniktir. Fakat promisezincirlerle çalışırken aklımızda tutmamız gereken birkaç şey var.

promiseP1, P2 ve P3 olmak üzere üç vaatle aşağıdaki varsayımsal zinciri düşünün . Her promisebirinin bir başarı işleyicisi ve bir hata işleyicisi vardır, bu nedenle P1 için S1 ve E1, P2 için S2 ve E2 ve P3 için S3 ve E3:

xhrCall()
  .then(S1, E1) //P1
  .then(S2, E2) //P2
  .then(S3, E3) //P3

Hata olmayan normal akışlarda, uygulama S1, S2 ve son olarak S3'ten akacaktır. Ancak gerçek hayatta işler asla bu kadar pürüzsüz değildir. P1 bir hatayla karşılaşabilir veya P2, E1 veya E2'yi tetikleyerek bir hatayla karşılaşabilir.

Aşağıdaki durumları göz önünde bulundurun:

• P1'deki sunucudan başarılı bir yanıt alıyoruz, ancak döndürülen veriler doğru değil veya sunucuda kullanılabilir veri yok (boş diziyi düşünün). Böyle bir durumda, bir sonraki vaat P2 için, hata işleyicisini E2 tetiklemelidir.

• P2 sözü için E2'yi tetikleyen bir hata alırız. Ancak işleyicinin içinde, uygulamanın normal şekilde yüklenmesini sağlayan önbellekten veriler var. Bu durumda, E2'den sonra S3'ün çağrılmasını sağlamak isteyebiliriz.

Dolayısıyla, her başarı veya hata işleyici yazdığımızda, şu anki fonksiyonumuz göz önüne alındığında, bu söz bir söz veya başarı zincirindeki bir sonraki işleyici için bir başarı mı yoksa başarısız mıdır?

Başarı işleyicisini zincirdeki bir sonraki vaat için tetiklemek istiyorsak, başarı veya hata işleyicisinden bir değer döndürebiliriz

Öte yandan, zincirdeki bir sonraki vaat için hata işleyiciyi tetiklemek istiyorsak, bunu bir deferrednesneyi kullanarak ve reject()yöntemini çağırarak yapabiliriz

Şimdi ertelenmiş nesne nedir?

JQuery'deki ertelenmiş nesneler, daha sonra, genellikle eşzamansız olarak tamamlanacak bir iş birimini temsil eder. İş birimi tamamlandığında, deferrednesne çözümlenmiş veya başarısız olarak ayarlanabilir.

Bir deferrednesne bir nesne içerir promise. Via promisenesnenin Eğer işin birimi tamamlandığında ne olacağı belirtebilirsiniz. Bunu, promisenesnenin geri arama işlevlerini ayarlayarak yaparsınız .

Jquery'de ertelenen nesneler: https://api.jquery.com/jquery.deferred/

AngularJ'lerde ertelenmiş nesneler: https://docs.angularjs.org/api/ng/service/ $ q


3
Çok iyi yazılmış. Bu gerçekten vaatlerde bulunmamı sağladı.
Ju66ernaut

İkinci parametre olan hata giderici her zaman isteğe bağlı mı?
1.21 gigawatts

Bu şimdiye kadar gördüğüm en iyi cevap!
İmam Bux

78

then () işlevi, jQuery veya AngularJS gibi bazı kitaplıklarda veya çerçevelerde kullanılan "Javascript vaatleri" ile ilgilidir.

Bir söz, eşzamansız işlemleri yürütmek için bir modeldir. Söz, geri çağrı olarak kullanılacak işlevleri belirtmenizi sağlayan "sonra" adlı bir yöntemi çağırmanıza olanak tanır.

Daha fazla bilgi için bkz. Http://wildermuth.com/2013/8/3/JavaScript_Promises

Açısal vaatler için: http://liamkaufman.com/blog/2013/09/09/using-angularjs-promises/


4
görev tamamlandığında yürütülen bir geri arama gibi mi? Nasıl farklı
Muhammed Umer

3
JavaScript Promises diğer yorum diyor de: A promise can only succeed or fail onceveIf a promise has succeeded or failed and you later add a success/failure callback, the correct callback will be called
Xiao

Ayrıca, Promise nuggets nasıl kullanılacağını promiseve ne yapılacağını açıklıyorcallback
Xiao

İlk sayfada eksik kod parçaları var (büyük beyaz boşluklar). Çoğu insan unsuru teftiş etmeyi düşünür ve kemanın URL'lerini altında bulur. Bu mesaj geri kalanı için - kemanlar hala çalışıyor;)
DanteTheSmith

1
@MuhammadUmer: Bu okuma stackoverflow.com/a/31453579/1350476 (Sid tarafından yanıt)
SharpCoder

32

Bildiğim kadarıyla, bu yazıda yerleşik bir then()yöntem yoktur javascript.

Görünüşe göre doSome("task")geri dönen ne olursa olsun bir yöntem var then.

doSome()Konsolun dönüş sonucunu günlüğe kaydederseniz, döndürülenlerin özelliklerini görebilmeniz gerekir.

console.log( myObj.doSome("task") ); // Expand the returned object in the
                                     //   console to see its properties.

GÜNCELLEME (ECMAScript6 itibarıyla) : -

.then()Fonksiyon saf javascript dahil edilmiştir.

Buradaki Mozilla belgelerinden ,

Then () yöntemi bir Promise döndürür. İki argüman alır: Sözün başarı ve başarısızlık durumları için geri arama işlevleri.

Promise nesnesi, sırayla,

Promise nesnesi, ertelenmiş ve eşzamansız hesaplamalar için kullanılır. Bir Söz henüz tamamlanmamış ancak gelecekte beklenen bir operasyonu temsil eder.

Yani, Promisehenüz hesaplanmamış ancak gelecekte çözülmesi gereken bir değer için yer tutucu görevi görür. Ve .then()işlev, söz verildiğinde çözüldüğünde çağrılacak işlevleri bir başarı veya başarısızlık olarak ilişkilendirmek için kullanılır.


12
O zamanlar yerleşik bir şey yoktu .then, ama şimdi ES6'da yerel vaatler geliyor: html5rocks.com/en/tutorials/es6/promises
janfoeh

Bu cevap için teşekkürler, bazı serin söz geri arama bekliyordum ama döndürülen 'sonra' adlı gerçek bir işlev olduğu ortaya çıktı.
spartikus

15

İşte işlerin nasıl yürüdüğünü netleştirmek için kendime yaptığım bir şey. Sanırım başkaları da bu somut örneği faydalı bulabilir:

doit().then(function() { log('Now finally done!') });
log('---- But notice where this ends up!');

// For pedagogical reasons I originally wrote the following doit()-function so that 
// it was clear that it is a promise. That way wasn't really a normal way to do 
// it though, and therefore Slikts edited my answer. I therefore now want to remind 
// you here that the return value of the following function is a promise, because 
// it is an async function (every async function returns a promise). 
async function doit() {
  log('Calling someTimeConsumingThing');
  await someTimeConsumingThing();
  log('Ready with someTimeConsumingThing');
}

function someTimeConsumingThing() {
  return new Promise(function(resolve,reject) {
    setTimeout(resolve, 2000);
  })
}

function log(txt) {
  document.getElementById('msg').innerHTML += txt + '<br>'
}
<div id='msg'></div>


5

İşte küçük bir JS_Fiddle.

o zaman vaat çözüldükten sonra kullanılabilen bir yöntem geri çağrı yığınıdır, jQuery gibi kütüphanenin bir parçasıdır, ancak şimdi yerel JavaScript'te mevcuttur ve aşağıda nasıl çalıştığı ayrıntılı bir açıklamadır.

Yerel JavaScript'te bir Promise yapabilirsiniz: jQuery'de vaatler olduğu gibi, Her vaat yığılabilir ve ardından Geri çağrıları Çöz ve Reddet ile çağrılabilir, Asenkron çağrıları bu şekilde zincirleyebilirsiniz.

Pil şarj durumu için MSDN Docs'tan çatalladım ve düzenledim.

Bunun yaptığı şey, kullanıcı dizüstü bilgisayarının veya cihazının pil şarj edip etmediğini bulmaya çalışmaktır. sonra denir ve işinizi başarı sonrası yapabilirsiniz.

navigator
    .getBattery()
    .then(function(battery) {
       var charging = battery.charging;
       alert(charging);
    })
    .then(function(){alert("YeoMan : SINGH is King !!");});

Başka bir es6 örneği

function fetchAsync (url, timeout, onData, onError) {
    
}
let fetchPromised = (url, timeout) => {
    return new Promise((resolve, reject) => {
        fetchAsync(url, timeout, resolve, reject)
    })
}
Promise.all([
    fetchPromised("http://backend/foo.txt", 500),
    fetchPromised("http://backend/bar.txt", 500),
    fetchPromised("http://backend/baz.txt", 500)
]).then((data) => {
    let [ foo, bar, baz ] = data
    console.log(`success: foo=${foo} bar=${bar} baz=${baz}`)
}, (err) => {
    console.log(`error: ${err}`)
})

Definition :: then Asenkron geri çağrıları çözmek için kullanılan bir yöntemdir

bu ES6'da tanıtıldı

Lütfen uygun belgeleri burada bulabilirsiniz Es6 Promises


Cevabınız aslında soruyu cevaplamıyor. API kullanımının sadece nereden thengeldiğini ve nasıl çalıştığını açıklamadan bir örnek sağlar . Bu ayrıntıları sağlamak için cevabınızı geliştirmelisiniz.
Didier L

@TarandeepSingh - önce pil durumunu bildirdiğiniz ifadede herhangi bir sözlü nesne döndürülmez. O zaman ikincisinin kullanımı nedir
Mohit Jain

@MohitJain Yeni bir vaadiniz olmasa bile birden fazla geri arama yapabileceğinizi gösterir. Çünkü, birden fazla çağrı Promise.all ile de yapılabilir.
Tarandeep Singh

" Yöntem geri arama yığını " ile ne demek istiyorsun ?
Bergi

4

DoSome, aynı zamanda bir yöntemi olan myObj olan bu döndürür şüpheli. Standart yöntem zinciri ...

doSome bunu döndürmüyorsa, doSome'un yürütüldüğü nesne olarak, bir nesnenin bir then yöntemiyle döndüğünden emin olabilirsiniz ...

@patrick'in işaret ettiği gibi, standart js için ()


1
DoSome'un bunu döndürdüğünden şüpheliyim - hiçbir şey bu tür askıya almaları zorlamaz / haklı çıkarmaz
Salathiel Genèse

1

doSome ("task") bir söz nesnesi döndürüyor olmalı ve bu söz her zaman bir fonksiyona sahip olmalıdır. Yani kodunuz şöyle

promise.then(function(env) {
    // logic
}); 

ve bunun sadece üye işlevine sıradan bir çağrı olduğunu biliyorsunuz.


1

.then zaman uyumsuz işlevinde bir söz verir.

İyi bir örnek:

var doSome = new Promise(function(resolve, reject){
    resolve('I am doing something');
});

doSome.then(function(value){
    console.log(value);
});

Ona başka bir mantık eklemek için, reject('I am the rejected param')çağrıyı ekleyebilir ve console.log bunu ekleyebilirsiniz .


0

Bu durumda then(), yöntemin döndürdüğü nesnenin bir sınıf doSome()yöntemidir.



0

Başka bir örnek:

new Promise(function(ok) {
   ok( 
      /* myFunc1(param1, param2, ..) */
   )
}).then(function(){
     /* myFunc1 succeed */
     /* Launch something else */
     /* console.log(whateverparam1) */
     /* myFunc2(whateverparam1, otherparam, ..) */
}).then(function(){
     /* myFunc2 succeed */
     /* Launch something else */
     /* myFunc3(whatever38, ..) */
})

Aynı mantık ok fonksiyonlarını kısaca kullanarak:

new Promise((ok) =>
   ok( 
      /* myFunc1(param1, param2, ..) */
)).then(() =>
     /* myFunc1 succeed */
     /* Launch something else */
     /* Only ONE call or statment can be made inside arrow functions */
     /* For example, using console.log here will break everything */
     /* myFunc2(whateverparam1, otherparam, ..) */
).then(() =>
     /* myFunc2 succeed */
     /* Launch something else */
     /* Only ONE call or statment can be made inside arrow functions */
     /* For example, using console.log here will break everything */
     /* myFunc3(whatever38, ..) */
)


-4

Ben yaklaşık 8 yıl geç kaldım, iyi ... neyse, o zaman () ne yaptığını gerçekten bilmiyorum ama belki MDN'nin bir cevabı olabilir. Aslında, biraz daha anlayabilirim.

Bu size ihtiyacınız olan tüm bilgileri gösterecektir (umarım). Birisi bu bağlantıyı göndermediği sürece. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then

Format promise.prototype.then () Promise ve prototip tür değişkenler ama javascript değişkenleri gibi değil, yani navigator.getBattery (). Web'de zar zor kullanılır, bu, cihazın pili hakkında durumları, merak ediyorsanız MDN hakkında daha fazla bilgi ve daha fazlasını gösterir.

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.