Masalah yang Anda gambarkan adalah dua kali lipat.
- Program yang Anda tulis harus berperilaku tidak sinkron secara keseluruhan jika dilihat dari luar .
- Seharusnya tidak terlihat di situs panggilan apakah panggilan fungsi berpotensi menyerahkan kontrol atau tidak.
Ada beberapa cara untuk mencapai ini, tetapi mereka pada dasarnya bermuara pada
- memiliki banyak utas (pada tingkat abstraksi)
- memiliki berbagai macam fungsi di tingkat bahasa, yang semuanya disebut seperti ini
foo(4, 7, bar, quux)
.
Untuk (1), saya menyatukan forking dan menjalankan banyak proses, menghasilkan beberapa thread kernel, dan implementasi thread hijau yang menjadwalkan thread level bahasa-runtime ke thread kernel. Dari perspektif masalah, mereka sama. Di dunia ini, tidak ada fungsi yang pernah menyerah atau kehilangan kendali dari perspektif utasnya . The benang itu sendiri kadang-kadang tidak memiliki kontrol dan kadang-kadang tidak berjalan tetapi Anda tidak menyerah kontrol thread sendiri di dunia ini. Suatu sistem yang cocok dengan model ini mungkin atau mungkin tidak memiliki kemampuan untuk menelurkan utas baru atau bergabung pada utas yang sudah ada. Sistem yang cocok dengan model ini mungkin atau mungkin tidak memiliki kemampuan untuk menduplikasi utas seperti yang dimiliki Unix fork
.
(2) menarik. Untuk melakukannya keadilan kita perlu berbicara tentang formulir pengenalan dan penghapusan.
Saya akan menunjukkan mengapa implisit await
tidak dapat ditambahkan ke bahasa seperti Javascript dengan cara yang kompatibel dengan mundur. Ide dasarnya adalah bahwa dengan mengekspos janji kepada pengguna dan memiliki perbedaan antara konteks sinkron dan asinkron, Javascript telah membocorkan detail implementasi yang mencegah penanganan fungsi sinkron dan asinkron secara seragam. Ada juga fakta bahwa Anda tidak bisa await
menjanjikan di luar tubuh fungsi async. Pilihan desain ini tidak kompatibel dengan "membuat asinkron tidak terlihat oleh penelepon".
Anda dapat memperkenalkan fungsi sinkron menggunakan lambda dan menghilangkannya dengan panggilan fungsi.
Pengantar fungsi sinkron:
((x) => {return x + x;})
Penghapusan fungsi sinkron:
f(4)
((x) => {return x + x;})(4)
Anda dapat membandingkan ini dengan pengenalan dan eliminasi fungsi asinkron.
Pengenalan fungsi asinkron
(async (x) => {return x + x;})
Penghapusan fungsi asynchonrous (catatan: hanya valid di dalam suatu async
fungsi)
await (async (x) => {return x + x;})(4)
Masalah mendasar di sini adalah bahwa fungsi asinkron juga merupakan fungsi sinkron yang menghasilkan objek janji .
Berikut adalah contoh memanggil fungsi asinkron secara sinkron di node.js repl.
> (async (x) => {return x + x;})(4)
Promise { 8 }
Anda secara hipotetis dapat memiliki bahasa, bahkan yang diketik secara dinamis, di mana perbedaan antara panggilan fungsi asinkron dan sinkron tidak terlihat di situs panggilan dan mungkin tidak terlihat di situs definisi.
Mengambil bahasa seperti itu dan menurunkannya ke Javascript dimungkinkan, Anda hanya perlu secara efektif membuat semua fungsi tidak sinkron.