Apa artinya fungsi dari () di JavaScript?

275

Saya telah melihat kode yang terlihat seperti:

myObj.doSome("task").then(function(env) {
    // logic
});

Dari mana datangnya then()?

Kay Pale
sumber
8
DIPERBARUI: Saya mengetahui bahwa itu ada hubungannya dengan janji-janji CommonJS
Kay Pale

Jawaban:

349

Cara tradisional untuk menangani panggilan asinkron dalam JavaScript adalah dengan panggilan balik. Katakanlah kita harus melakukan tiga panggilan ke server, satu demi satu, untuk mengatur aplikasi kita. Dengan panggilan balik, kode tersebut mungkin terlihat seperti berikut (dengan asumsi fungsi xhrGET untuk melakukan panggilan server):

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

Dalam contoh ini, pertama-tama kita mengambil konfigurasi server. Kemudian berdasarkan itu, kami mengambil informasi tentang pengguna saat ini, dan akhirnya mendapatkan daftar item untuk pengguna saat ini. Setiap panggilan xhrGET mengambil fungsi panggilan balik yang dieksekusi ketika server merespons.

Sekarang tentu saja semakin banyak level sarang yang kita miliki, semakin sulit kodenya untuk membaca, men-debug, memelihara, meningkatkan, dan pada dasarnya bekerja dengannya. Ini umumnya dikenal sebagai neraka panggilan balik. Juga, jika kita perlu menangani kesalahan, kita mungkin perlu meneruskan fungsi lain untuk setiap panggilan xhrGET untuk memberi tahu apa yang perlu dilakukan jika terjadi kesalahan. Jika kita ingin memiliki satu penangan kesalahan yang umum, itu tidak mungkin.

API Janji dirancang untuk mengatasi masalah bersarang ini dan masalah penanganan kesalahan.

API Janji mengusulkan yang berikut:

  1. Setiap tugas yang tidak sinkron akan mengembalikan promiseobjek.
  2. Setiap promiseobjek akan memiliki thenfungsi yang dapat mengambil dua argumen, success pawang dan errorpawang.
  3. Keberhasilan atau penangan kesalahan dalam thenfungsi akan dipanggil hanya sekali , setelah tugas asinkron selesai.
  4. The thenFungsi juga akan mengembalikan promise, untuk memungkinkan chaining beberapa panggilan.
  5. Setiap handler (berhasil atau salah) dapat mengembalikan a value, yang akan diteruskan ke fungsi berikutnya sebagai argument, dalam rantai promises.
  6. Jika pawang mengembalikan promise(membuat permintaan asinkron lain), maka pawang berikutnya (sukses atau kesalahan) akan dipanggil hanya setelah permintaan itu selesai.

Jadi kode contoh sebelumnya mungkin diterjemahkan menjadi sesuatu seperti yang berikut, menggunakan janji dan $httplayanan (dalam AngularJs):

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

Menyebarkan Keberhasilan dan Kesalahan

Chaining menjanjikan adalah teknik yang sangat kuat yang memungkinkan kita untuk menyelesaikan banyak fungsi, seperti memiliki layanan melakukan panggilan server, melakukan beberapa postprocessing data, dan kemudian mengembalikan data yang diproses ke controller. Tetapi ketika kita bekerja dengan promiserantai, ada beberapa hal yang perlu kita ingat.

Pertimbangkan promiserantai hipotetis berikut dengan tiga janji, P1, P2, dan P3. Masing-masing promisememiliki penangan sukses dan penangan kesalahan, jadi S1 ​​dan E1 untuk P1, S2 dan E2 untuk P2, dan S3 dan E3 untuk P3:

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

Dalam aliran hal-hal normal, di mana tidak ada kesalahan, aplikasi akan mengalir melalui S1, S2, dan akhirnya, S3. Namun dalam kehidupan nyata, segalanya tidak pernah semulus itu. P1 mungkin mengalami kesalahan, atau P2 mungkin mengalami kesalahan, memicu E1 atau E2.

Pertimbangkan kasus-kasus berikut:

• Kami menerima respons yang berhasil dari server di P1, tetapi data yang dikembalikan tidak benar, atau tidak ada data yang tersedia di server (pikirkan array kosong). Dalam kasus seperti itu, untuk P2 janji berikutnya, itu harus memicu penangan kesalahan E2.

• Kami menerima kesalahan untuk P2 janji, memicu E2. Tetapi di dalam handler, kami memiliki data dari cache, memastikan bahwa aplikasi dapat memuat seperti biasa. Dalam hal ini, kami mungkin ingin memastikan bahwa setelah E2, S3 dipanggil.

Jadi setiap kali kita menulis sukses atau penangan kesalahan, kita perlu menelepon — mengingat fungsi kita saat ini, apakah janji ini berhasil atau gagal bagi penangan berikutnya dalam rantai janji?

Jika kita ingin memicu penangan sukses untuk janji berikutnya dalam rantai, kita bisa mengembalikan nilai dari keberhasilan atau penangan kesalahan

Jika, di sisi lain, kami ingin memicu penangan kesalahan untuk janji berikutnya dalam rantai, kita bisa melakukannya menggunakan deferredobjek dan memanggil reject()metode

Sekarang Apa objek yang ditangguhkan?

Objek yang ditangguhkan di jQuery mewakili unit kerja yang akan diselesaikan kemudian, biasanya secara tidak sinkron. Setelah unit kerja selesai, deferredobjek dapat diatur untuk diselesaikan atau gagal.

Sebuah deferredobjek berisi sebuah promiseobjek. Melalui promiseobjek Anda dapat menentukan apa yang akan terjadi ketika unit kerja selesai. Anda melakukannya dengan mengatur fungsi panggilan balik pada promiseobjek.

Objek yang ditangguhkan di Jquery: https://api.jquery.com/jquery.deferred/

Objek yang ditangguhkan di AngularJs: https://docs.angularjs.org/api/ng/service/ $ q

Sid
sumber
3
Ditulis dengan sangat baik. Ini telah membantu saya benar-benar menepati janji.
Ju66ernaut
Apakah penangan kesalahan, parameter kedua, selalu opsional?
1,21 gigawatt
Sejauh ini, inilah jawaban terbaik yang pernah saya lihat sejauh ini!
Imam Bux
78

kemudian () fungsi terkait dengan "janji Javascript" yang digunakan di beberapa perpustakaan atau kerangka kerja seperti jQuery atau AngularJS.

Janji adalah pola untuk menangani operasi asinkron. Janji itu memungkinkan Anda untuk memanggil metode yang disebut "lalu" yang memungkinkan Anda menentukan fungsi yang akan digunakan sebagai panggilan balik.

Untuk informasi lebih lanjut, lihat: http://wildermuth.com/2013/8/3/JavaScript_Promises

Dan untuk janji-janji Angular: http://liamkaufman.com/blog/2013/09/09/using-angularjs-promises/

almoraleslopez
sumber
4
jadi itu seperti panggilan balik yang dijalankan ketika tugas selesai? Bagaimana perbedaannya
Muhammad Umer
3
yang JavaScript Janji dalam komentar lain mengatakan: A promise can only succeed or fail once, danIf a promise has succeeded or failed and you later add a success/failure callback, the correct callback will be called
Xiao
Juga, nugget Janji menjelaskan cara menggunakan promisedan apa yang akan dilakukan dengancallback
Xiao
Pada halaman pertama, ada potongan kode yang hilang (kosong putih besar). Sebagian besar orang akan berpikir untuk memeriksa elemen dan menemukan URL biola di bawahnya. Pesan ini untuk yang lain - biola masih berfungsi;)
DanteTheSmith
1
@MuhammadUmer: baca stackoverflow.com/a/31453579/1350476 ini (dijawab oleh Sid)
SharpCoder
32

Setahu saya, tidak ada then()metode built-in di javascript(pada saat penulisan ini).

Tampaknya apa pun yang doSome("task")dikembalikan memiliki metode yang disebut then.

Jika Anda mencatat hasil pengembalian doSome()ke konsol, Anda harus dapat melihat properti dari apa yang dikembalikan.

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

UPDATE (Pada ECMAScript6) : -

The .then()Fungsi telah dimasukkan ke javascript murni.

Dari dokumentasi Mozilla di sini ,

Metode then () mengembalikan Janji. Dibutuhkan dua argumen: fungsi callback untuk kasus-kasus Janji dan kegagalan.

Objek Janji, pada gilirannya, didefinisikan sebagai

Objek Janji digunakan untuk perhitungan yang ditangguhkan dan tidak sinkron. Suatu Janji mewakili operasi yang belum selesai, tetapi diharapkan di masa depan.

Artinya, Promisebertindak sebagai pengganti untuk nilai yang belum dihitung, tetapi harus diselesaikan di masa depan. Dan .then()fungsi tersebut digunakan untuk mengaitkan fungsi yang akan dipanggil pada Janji ketika itu diselesaikan - baik sebagai keberhasilan atau kegagalan.

pengguna113716
sumber
12
Tidak ada built-in .thensaat itu, tetapi janji-janji asli datang sekarang di ES6: html5rocks.com/en/tutorials/es6/promises
janfoeh
terima kasih atas jawaban ini, saya mengharapkan beberapa panggilan balik janji keren tapi ternyata fungsi sebenarnya disebut 'maka' yang dikembalikan.
spartikus
15

Ini adalah sesuatu yang saya buat untuk diri saya sendiri untuk menjernihkan cara kerja. Saya kira orang lain juga dapat menemukan contoh konkret ini berguna:

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>

Magnus
sumber
5

Ini JS_Fiddle kecil .

kemudian adalah metode callback stack yang tersedia setelah janji diselesaikan itu adalah bagian dari perpustakaan seperti jQuery tetapi sekarang tersedia dalam JavaScript asli dan di bawah ini adalah penjelasan detail cara kerjanya

Anda dapat melakukan Janji dalam JavaScript asli: sama seperti ada janji di jQuery, Setiap janji dapat ditumpuk dan kemudian dapat dipanggil dengan Putuskan dan Tolak panggilan balik, Ini adalah bagaimana Anda dapat membuat panggilan panggilan tidak sinkron.

Saya bercabang dan Diedit dari MSDN Documents pada status pengisian daya baterai ..

Apa yang dilakukan adalah mencoba mencari tahu apakah pengguna laptop atau perangkat sedang mengisi baterai. kemudian dipanggil dan Anda dapat melakukan pos pekerjaan Anda sukses.

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

Contoh es6 lainnya

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 adalah metode yang digunakan untuk memecahkan panggilan balik Asynchronous

ini diperkenalkan dalam ES6

Silakan temukan dokumentasi yang tepat di sini Es6 Promises

Tarandeep Singh
sumber
Jawaban Anda sebenarnya tidak menjawab pertanyaan. Ini hanya memberikan contoh penggunaan API tanpa menjelaskan dari mana thenasalnya dan bagaimana cara kerjanya. Anda harus meningkatkan jawaban Anda untuk memberikan perincian itu.
Didier L
@TarandeepSingh - dalam pernyataan pertama kemudian di mana Anda memberitahukan status baterai tidak ada objek janji dikembalikan. Lalu apa gunanya yang kedua lalu
Mohit Jain
@MohitJain Ini memamerkan Anda dapat melakukan beberapa panggilan balik bahkan jika Anda tidak memiliki janji baru. Karena, beberapa panggilan juga dapat dilakukan dengan Promise.all.
Tarandeep Singh
WTH yang Anda maksud dengan " method callback stack "?
Bergi
4

Saya menduga doSome mengembalikan ini, yang merupakan myObj, yang juga memiliki metode kemudian. Rantai metode standar ...

Jika doSome tidak mengembalikan ini, menjadi objek yang doSome dieksekusi, yakinlah itu mengembalikan beberapa objek dengan metode kemudian ...

sebagai @patrick menunjukkan, tidak ada maka () untuk js standar

hvgotcodes
sumber
1
Saya menduga doSome mengembalikan ini - tidak ada yang memberlakukan / membenarkan penangguhan tersebut
Salathiel Genèse
1

doSome ("task") harus mengembalikan objek janji, dan janji itu selalu memiliki fungsi. Jadi kode Anda sama seperti ini

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

dan Anda tahu ini hanyalah panggilan biasa ke fungsi anggota.

Hardeep SINGH
sumber
1

.then mengembalikan janji dalam fungsi async.

Contoh yang bagus adalah:

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

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

Untuk menambahkan logika lain ke dalamnya, Anda juga dapat menambahkan fungsi reject('I am the rejected param')panggilan dan console.log itu.

appdesigns
sumber
0

Dalam hal ini then()adalah metode kelas dari objek yang dikembalikan oleh doSome()metode.


sumber
0

Fungsi ".then ()" adalah wideley yang digunakan untuk objek yang dijanjikan dalam pemrograman Asynchoronus Untuk Windows 8 Store Apps. Sejauh yang saya mengerti itu berfungsi beberapa cara seperti panggilan balik.

Temukan Detail di Documentantion ini http://msdn.microsoft.com/en-us/library/windows/apps/hh700330.aspx

Sebab itu bisa juga nama untuk fungsi yang didefinisikan lainnya.

pengguna2508620
sumber
0

Contoh lain:

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, ..) */
})

Logika yang sama menggunakan fungsi panah singkatan:

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, ..) */
)

NVRM
sumber
-4

Saya terlambat sekitar 8 tahun, well ... Bagaimanapun, saya tidak benar-benar tahu apa yang kemudian () lakukan tetapi mungkin MDN mungkin punya jawaban. Sebenarnya, saya mungkin lebih memahaminya.

Ini akan menunjukkan kepada Anda semua informasi (mudah-mudahan), yang Anda butuhkan. Kecuali seseorang telah memposting tautan ini. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then

Formatnya adalah prom.prototype.then () Janji dan prototipe adalah sejenis variabel tetapi tidak seperti variabel dalam javascript, maksud saya seperti hal-hal lain pergi ke sana seperti navigator.getBattery (). Lalu () di mana ini sebenarnya ada tetapi jarang digunakan di web, yang ini menunjukkan status tentang baterai perangkat, informasi lebih lanjut dan lebih banyak tentang MDN jika Anda penasaran.

Jonathan J. Pecany
sumber