ECMAScript7 async/menunggu perilaku tidak konsisten tergantung pada apakah menggunakan tanda kurung dalam fungsi panah atau tidak

Saya mengalami perilaku yang tidak konsisten di Google Chrome 60.0.3112.78 (Pembuatan Resmi) (64-bit) saat menggunakan async/menunggu ES6+ modern, bergantung pada apakah saya menggunakan tanda kurung di fungsi panah yang mengembalikan Janji. Hal yang sama terjadi di Node.js. Saya kesulitan memahami alasannya.

Saya memahami bahwa ini bukan cara mengimplementasikan fungsi sleep() tetapi ini adalah cara termudah untuk mendemonstrasikannya. Perhatikan cuplikan kode contoh berikut.

function sleep(ms = 0) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

(async () => {
  console.log('a');
  await sleep(5000);
  console.log('b');
})()

Seperti yang diharapkan, ini akan menulis a ke konsol, tunggu 5 detik dan kemudian menulis b ke konsol.


Notasi yang lebih pendek menggunakan fungsi panah untuk mengembalikan Janji.

const sleep = ms => { return new Promise(resolve => setTimeout(resolve, ms)) }

(async () => {
  console.log('a');
  await sleep(5000);
  console.log('b');
})()

Seperti yang diharapkan, kode ini berperilaku sama. a dan b ditulis ke konsol dengan interval 5000 milidetik di antaranya.


Kode berikut tidak berfungsi. Satu-satunya perbedaan adalah saya tidak membungkus kembalinya Janji dalam tanda kurung pada baris pertama.

const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))

(async () => {
  console.log('a');
  await sleep(5000);
  console.log('b');
})()

Dalam hal ini, menunggu tidur tidak berfungsi. Faktanya, kode ini tidak melakukan apa pun. Itu tidak mencatat apa pun ke konsol, tidak a dan tidak b.

Saya menganggap diri saya cukup berpengalaman tetapi saat ini saya tidak memahami hal ini. Mengapa tanda kurung penting dalam kasus khusus ini? Nilai kembaliannya identik, bukan? Dan kenapa karakter a tidak dicatat di konsol?

Seseorang tolong jelaskan kepada saya secara tepat dan spesifik mengapa hal ini terjadi. Apakah ini bug atau saya sendiri yang hanya perlu tidur?

Terima kasih banyak.


person Jochem Stoel    schedule 04.08.2017    source sumber
comment
comment
@4castle Jika Anda merujuk pada jawaban ini, saya sarankan untuk menggunakan fungsi deklarasi (function sleep(ms) { return … }) yang tidak memerlukan titik koma sama sekali :-)   -  person Bergi    schedule 05.08.2017


Jawaban (1)


Yang penting adalah titik koma setelah fungsi panah. Menulis

const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
//                                                                 ^

dan itu akan berhasil. Perhatikan bahwa baris berikutnya dimulai dengan (, yang merupakan kelanjutan yang valid secara sintaksis, sehingga ASI tidak masuk. Kode Anda diurai dan ditafsirkan sebagai

const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))(async () => { … })()

tapi fungsinya sleep tidak pernah dipanggil.

person Bergi    schedule 04.08.2017
comment
@Matthew Memang benar, tetapi jika Anda ingin menghilangkan titik koma dan membiarkannya dimasukkan secara otomatis jika memungkinkan, Anda harus perlu menempatkan satu di awal setiap baris yang dimulai dengan (, [, /, +, - atau `. - person Bergi; 05.08.2017
comment
Haha ya, tapi ketidakjelasan bug ini membuat saya menghargai penekanan tombol ekstra. - person Wolfie; 05.08.2017
comment
Terima kasih! Anda benar, saya tidak percaya saya melewatkannya. Fiuh! Sebagai tambahan, saya sebenarnya secara religius tidak pernah menggunakan titik koma kecuali tidak ada cara lain dan yakin Anda dapat mengidentifikasi pengembang yang baik dengan kebiasaan ini. Tapi saya bias. Terima kasih lagi! :) - person Jochem Stoel; 05.08.2017
comment
Alasannya adalah lebih mudah untuk selalu menyertakan titik koma daripada mencoba mengingat kapan titik koma diperlukan atau tidak, sehingga mengurangi kemungkinan terjadinya kesalahan. - person Jaime; 05.08.2017
comment
@JochemStoel Saya akan menebaknya jika Anda menghilangkannya dalam fungsi async juga :-) - person Bergi; 05.08.2017
comment
@Jaime saya tidak setuju. Harus mengingat setiap saat apakah Anda perlu menggunakan titik koma atau tidak membuat Anda tetap fokus sebagai pengembang. Itu memaksa Anda melakukannya. Tidak ada yang menggunakan auto-pilot. - person Jochem Stoel; 06.08.2017
comment
@JochemStoel Saya berasumsi bahwa Anda membuang setidaknya satu jam untuk mencari tahu mengapa kode Anda tidak berfungsi seperti yang diharapkan. Penyisipan titik koma otomatis (ASI) dianggap sebagai salah satu fitur JavaScript yang lebih kontroversial. Kita harus memperlakukan ASI seolah-olah ASI tidak ada. - person Jaime; 07.08.2017
comment
@Jaime Kita tidak boleh melupakan titik koma. Apakah di akhir setiap baris, atau di awal setiap baris (yang dimulai dengan tanda kurung) tidak menjadi masalah. Ini sepenuhnya merupakan preferensi pribadi, dan setelah Anda terbiasa dengan metode mana pun, Anda akan dapat menemukan metode yang hilang dengan mudah. Atau biarkan linter Anda yang melakukannya, ada aturan untuk kedua gaya tersebut. - person Bergi; 07.08.2017
comment
@Bergi, maukah Anda memperbarui jawaban Anda untuk memasukkan kode OP dengan titik koma di depan sebelum IIFE? - person Mihail Malostanidis; 03.03.2018
comment
@MihailMalostanidis Tidak, bukankah menyertakan bagian yang sudah diperbaiki sudah cukup? - person Bergi; 03.03.2018