Callback Hell
Untuk programmer JavaScript, menangani panggilan balik itu sederhana, tetapi menangani panggilan balik dengan level yang terlalu dalam tidak begitu indah. Cuplikan kode sampel berikut menggunakan panggilan balik tiga lapis, dan kemudian mengisi kembali otak untuk lebih banyak lapisan adegan. Itu hanya asam. Ini adalah neraka panggilan balik legendaris.
getDirectories (function (dirs) {getFiles (dirs [0], function (file) {getContent (file [0], function (file, konten) {console.log ('fileName:', file); console.log (konten);});});}); function getDirectories (callback) {setTimeOut (function () {callback (['/home/ben']);}, 1000);} function getFiles (dir, callback) {setTimeout (function () {callback ([dir + '/test1.txt', dirtimeout (function () {callback);};},} {} {Dir + '/txtx', callback ', callback', Function {Dir + ', Function {Dir +', Function {Dir '/Dir, setTimeout (function () {callback (file, 'content');}, 1000)}Larutan
Ada banyak solusi asinkron dalam ekosistem yang dapat menangani masalah neraka callback, seperti Bluebird, Q, dll. Artikel ini berfokus pada dukungan untuk pemrograman asinkron dalam spesifikasi ECMASCRIPT 6/7.
Janji es6
Janji adalah solusi untuk pemrograman asinkron dan alat yang ampuh untuk menyelesaikan masalah neraka callback.
Janji diterima secara arus utama dalam ekosistem JavaScript pada tahun 2007 ketika kerangka kerja Dojo menambahkan fungsionalitas dojo.deferikan. Dengan popularitas dojo.dial, pada tahun 2009, Kris Zyp mengusulkan janji CommonJS/spesifikasi. Selanjutnya, sejumlah besar implementasi janji muncul di ekosistem, termasuk Q.js, futuresjs, dll. Tentu saja, popularitas janji sebagian besar disebabkan oleh keberadaan jQuery, tetapi jQuery tidak sepenuhnya mematuhi janji CommonJS/spesifikasi. Kemudian seperti yang Anda lihat, spesifikasi ES 6 termasuk janji.
Janji dijelaskan dalam MDN sebagai berikut:
Objek janji adalah proxy untuk nilai pengembalian, yang mungkin tidak diketahui ketika objek janji dibuat. Ini memungkinkan Anda untuk menentukan metode penanganan untuk keberhasilan atau kegagalan operasi asinkron. Ini memungkinkan metode asinkron untuk mengembalikan nilai seperti metode sinkron: metode asinkron mengembalikan yang berisi nilai pengembalian asli
Kode berikut adalah contoh di bagian "Callback Hell" yang diimplementasikan melalui janji. Kode ini tidak terlihat sangat ringkas, tetapi telah meningkat secara signifikan dibandingkan dengan callback hierarkis tradisional, dan kodenya lebih dapat dipelihara dan dibaca.
getDirectories (). Lalu (function (dirs) {return getFiles (dirs [0]);}). Kemudian (fungsi (file) {return getContent (file [0]);}). Kemudian (function (val) {console.log ('fileName:', val.file); console.log (val.content ('fileName:', val.file); console.log (val.content ('); function getDirectories () {return new janji (function (resolve, reject) {setTimeOut (function () {resolve (['/home/ben']);}, 1000);});} function getFiles (dir) {return new janji (function (resolve, reject) {setTimeout (function () {resolve) {return new janji (function (resolve, reject) {setTimeout (function () {resolve) {return new Promise (function (resolve, reject) {setTimeout (function () {resolve () (function '); Dirtx (dirtx/{setTimeOut (function () {resolve (); }, 1000);});} function getContent (file) {return new janji (function (resolve, reject) {setTimeOut (function () {resolve ({file: file, konten: 'content'});}, 1000);});}Generator ES6
Implementasi janji tidak cukup ringkas, kami masih membutuhkan pilihan yang lebih baik, CO adalah salah satu pilihan. CO adalah pengontrol aliran asinkron berdasarkan generator. Sebelum memahami Co, Anda perlu memahami generator terlebih dahulu. Siswa yang akrab dengan C# harus memahami bahwa versi C# 2.0 memperkenalkan kata kunci hasil untuk mengulangi generator. Generator ES 6 mirip dengan C#, dan juga menggunakan gula sintaks hasil, dan mengimplementasikan mesin negara secara internal. Untuk penggunaan tertentu, silakan merujuk ke bagian Fungsi Dokumen MDN, dan merujuk ke Blog Tim AlloyTeam untuk pemahaman mendalam tentang generator. Gunakan CO untuk secara cerdik menggabungkan generator ES6 dan ES6 berjanji untuk membuat panggilan asinkron lebih harmonis.
co (function* () {var dirs = hasil getDirectories (); var file = hasil getFiles (dirs [0]); var contentVal = hasil getContent (file [0]); console.log ('fileName:', contentVal.file); console.log (contentVal.content);CO sangat pintar, dan kode intinya dapat menyederhanakan contoh berikut. Gagasan umum adalah menggunakan generator traversal rekursif sampai negara selesai, tentu saja CO melakukan lebih banyak.
rungenerator (); fungsi* run () {var dirs = hasil getDirectories (); var file = hasil getFiles (dirs [0]); var contentVal = hasil getContent (file [0]); console.log ('nama file:', contentVal.file); console.log (contentVal.content);} function rungenerator () {var gen = run (); fungsi go (hasil) {if (result.done) return; result.value.then (function (r) {go (gen.next (r));}); } go (gen.next ());}ES7 Async/Await
ES6 Generator sangat bagus, tetapi sangat disayangkan bahwa saya membutuhkan dukungan dari perpustakaan pihak ketiga. Berita baiknya adalah bahwa ES 7 akan memperkenalkan kata kunci Async/Await untuk menyelesaikan masalah panggilan asinkron dengan sempurna. Nah, .NET adalah satu langkah di depan, dan .NET Framework 4.5 sudah menjadi yang pertama mendukungnya.
Kode masa depan akan ditulis seperti ini:
run (); fungsi async run () {var dirs = menunggu getDirectories (); var file = menunggu getFiles (dirs [0]); var contentVal = menunggu getContent (file [0]); console.log ('nama file:', contentVal.file); Console.log (ContentVal.Content);}sebagai kesimpulan
Dari metode pemrograman asinkron callback klasik, hingga peningkatan pemrograman asinkron dengan spesifikasi ES6 Promise, hingga pemrosesan elegan dari ko-kombinasi dengan generator ES, dan akhirnya akhir yang sempurna dari ES7 Async/Await, kita dapat memahami mengapa ecmascript memiliki fitur ini dan masalah apa yang diselesaikannya, dan melihat lebih jelas pengembangan Javascript.