Dengan contoh kode di bawah ini, apakah ada perbedaan dalam perilakunya, dan, jika ya, apa perbedaannya?
return await promise
async function delay1Second() {
return (await delay(1000));
}
return promise
async function delay1Second() {
return delay(1000);
}
Seperti yang saya pahami, yang pertama akan memiliki penanganan kesalahan dalam fungsi async, dan kesalahan akan menggelembung keluar dari Janji fungsi asinkron. Namun, yang kedua membutuhkan satu centang lebih sedikit. Apakah ini benar?
Cuplikan ini hanyalah fungsi umum untuk mengembalikan Janji sebagai referensi.
function delay(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
javascript
async-await
PitaJ
sumber
sumber
async
darireturn promise
sampel kedua ( ) Anda.promise.then(() => nestedPromise)
akan meratakan dan "mengikuti" itunestedPromise
. Menarik bagaimana ini berbeda dari tugas bersarang di C # di mana kita harus melakukannyaUnwrap
. Di samping catatan, tampaknyaawait somePromise
panggilanPromise.resolve(somePromise).then
, bukan hanyasomePromise.then
, dengan beberapa perbedaan semantik yang menarik.Jawaban:
Sering kali, tidak ada perbedaan yang dapat diamati antara
return
danreturn await
. Kedua versidelay1Second
memiliki perilaku observasi yang sama persis (tetapi bergantung pada implementasinya,return await
versi tersebut mungkin menggunakan lebih banyak memori karenaPromise
objek perantara mungkin dibuat).Namun, seperti yang ditunjukkan @PitaJ, ada satu kasus di mana terdapat perbedaan: jika
return
ataureturn await
berada di dalam bloktry
-catch
. Perhatikan contoh iniPada versi pertama, fungsi async menunggu janji yang ditolak sebelum mengembalikan hasilnya, yang menyebabkan penolakan tersebut diubah menjadi pengecualian dan
catch
klausa tercapai; fungsi ini kemudian akan mengembalikan sebuah janji yang diselesaikan ke string "Tersimpan!".Namun, versi kedua dari fungsi ini mengembalikan janji yang ditolak secara langsung tanpa menunggunya di dalam fungsi async , yang berarti
catch
kasus tidak dipanggil dan pemanggil mendapat penolakan.sumber
return new Promise(function(resolve, reject) { })
dalam satufor...of
loop dan kemudian memanggilresolve()
dalam loop setelahpipe()
tidak menghentikan eksekusi program sampai pipa telah selesai, seperti yang diinginkan, namun menggunakanawait new Promise(...)
tidak. apakah sintaks yang terakhir valid / benar? apakah ini 'singkatan' untukreturn await new Promise(...)
? dapatkah Anda membantu saya memahami mengapa yang terakhir berhasil dan yang pertama tidak? untuk konteks, skenario dalamsolution 02
dari jawaban iniSeperti jawaban lain yang disebutkan, kemungkinan ada sedikit manfaat kinerja saat membiarkan janji meluap dengan mengembalikannya secara langsung - hanya karena Anda tidak harus menunggu hasilnya terlebih dahulu dan kemudian membungkusnya dengan janji lain lagi. Namun, belum ada yang berbicara tentang pengoptimalan panggilan ekor .
Pengoptimalan panggilan ekor , atau "panggilan ekor yang tepat" , adalah teknik yang digunakan interpreter untuk mengoptimalkan tumpukan panggilan. Saat ini, belum banyak runtime yang mendukungnya - meskipun secara teknis merupakan bagian dari Standar ES6 - tetapi kemungkinan dukungan itu mungkin ditambahkan di masa mendatang, sehingga Anda dapat mempersiapkannya dengan menulis kode yang baik saat ini.
Singkatnya, TCO (atau PTC) mengoptimalkan tumpukan panggilan dengan tidak membuka bingkai baru untuk fungsi yang langsung dikembalikan oleh fungsi lain. Sebaliknya, itu menggunakan kembali bingkai yang sama.
Karena
delay()
langsung dikembalikan olehdelay1Second()
, runtime yang mendukung PTC pertama-tama akan membuka bingkai untukdelay1Second()
(fungsi luar), tetapi alih-alih membuka bingkai lain untukdelay()
(fungsi bagian dalam), itu hanya akan menggunakan kembali bingkai yang sama yang dibuka untuk fungsi luar. Ini mengoptimalkan stack karena dapat mencegah stack overflow (hehe) dengan fungsi rekursif yang sangat besar, misfibonacci(5e+25)
. Pada dasarnya ini menjadi loop, yang jauh lebih cepat.PTC hanya diaktifkan ketika fungsi bagian dalam langsung dikembalikan. Ini tidak digunakan ketika hasil dari fungsi diubah sebelum dikembalikan, misalnya, jika Anda memiliki
return (delay(1000) || null)
, ataureturn await delay(1000)
.Tapi seperti yang saya katakan, sebagian besar runtime dan browser belum mendukung PTC, jadi mungkin sekarang tidak membuat perbedaan besar, tetapi tidak ada salahnya untuk membuktikan kode Anda di masa mendatang.
Baca lebih lanjut dalam pertanyaan ini: Node.js: Apakah ada pengoptimalan untuk panggilan ekor dalam fungsi asinkron?
sumber
Ini adalah pertanyaan yang sulit untuk dijawab, karena ini tergantung pada bagaimana transpiler Anda (mungkin
babel
) benar-benar ditampilkanasync/await
. Hal-hal yang jelas:Kedua implementasi harus berperilaku sama, meskipun implementasi pertama mungkin memiliki satu implementasi yang lebih sedikit
Promise
di rantai.Terutama jika Anda membuang yang tidak diperlukan
await
, versi kedua tidak akan memerlukan kode tambahan dari transpiler, sedangkan versi pertama memerlukannya.Jadi dari perspektif kinerja kode dan debugging, versi kedua lebih disukai, meskipun hanya sedikit, sedangkan versi pertama memiliki sedikit manfaat keterbacaan, karena dengan jelas menunjukkan bahwa ia mengembalikan sebuah janji.
sumber
undefined
) dan yang kedua mengembalikan aPromise
.async/await
- saya merasa jauh lebih sulit untuk bernalar. @PitaJ benar, kedua fungsi mengembalikan Promise.try-catch
? Dalamreturn promise
kasus ini,rejection
tidak akan ada yang tertangkap, benar, sedangkan dalamreturn await promise
kasus, akan tertangkap , bukan?await
masing-masing di beberapa situs panggilan, hasilnya akan sangat berbeda.Perbedaan nyata: Penolakan janji ditangani di tempat yang berbeda
return somePromise
akan memberikan somePromise ke situs panggilan, danawait
somePromise untuk menetap di situs panggilan (jika ada). Oleh karena itu, jika somePromise ditolak, itu tidak akan ditangani oleh blok catch lokal, tetapi blok catch situs panggilan itu.return await somePromise
pertama-tama akan menunggu beberapa janji untuk menetap secara lokal. Oleh karena itu, nilai atau Pengecualian pertama-tama akan ditangani secara lokal. => Blok tangkapan lokal akan dieksekusi jikasomePromise
ditolak.Alasan:
return await Promise
menunggu baik di dalam maupun di luar,return Promise
hanya menunggu di luarLangkah Terperinci:
kembali Janji
delay1Second()
;delay1Second()
, fungsidelay(1000)
mengembalikan sebuah promise langsung dengan[[PromiseStatus]]: 'pending
. Sebut sajadelayPromise
.Promise.resolve()
( Sumber ). Karenadelay1Second
merupakan fungsi async, kami memiliki:Promise.resolve(delayPromise)
kembalidelayPromise
tanpa melakukan apa pun karena inputnya sudah menjadi promise (lihat MDN Promise.resolve ):await
menunggu sampaidelayPromise
diselesaikan.delayPromise
dipenuhi dengan PromiseValue = 1:delayPromise
ditolak:kembali menunggu Janji
delay1Second()
;delay1Second()
, fungsidelay(1000)
mengembalikan sebuah promise langsung dengan[[PromiseStatus]]: 'pending
. Sebut sajadelayPromise
.delayPromise
diselesaikan.delayPromise
dipenuhi dengan PromiseValue = 1:delayPromise
ditolak:Glosarium:
Promise.[[PromiseStatus]]
perubahan daripending
menjadiresolved
ataurejected
sumber
Di sini saya meninggalkan beberapa kode praktis agar Anda dapat memahami perbedaannya
fungsi "x" hanya adalah fungsi async daripada memiliki fucn lain jika akan menghapus kembali mencetak "lebih banyak kode ..."
variabel x hanyalah sebuah fungsi asynchronous yang pada gilirannya memiliki fungsi asynchronous lain, di kode utama kita memanggil menunggu untuk memanggil fungsi variabel x, ketika selesai maka mengikuti urutan kode, itu akan normal untuk "async / await", tetapi di dalam fungsi x terdapat fungsi asinkron lainnya, dan ini mengembalikan sebuah janji atau mengembalikan sebuah "janji" itu akan tetap berada di dalam fungsi x, melupakan kode utama, yaitu, tidak akan mencetak "console.log (" more code .. "), sebaliknya jika kita meletakkan" await "maka akan menunggu setiap fungsi selesai dan akhirnya mengikuti urutan normal dari kode utama.
di bawah "console.log (" finish 1 "hapus" return ", Anda akan melihat perilakunya.
sumber
Berikut adalah contoh skrip ketikan yang dapat Anda jalankan dan yakinkan diri Anda sendiri bahwa Anda perlu "kembali menunggu"
sumber