Saya mencoba membuat (lagi) bahasa yang mengkompilasi ke JavaScript. Salah satu fitur yang saya ingin miliki adalah kemampuan untuk melakukan operasi async JavaScript secara sinkron (tidak persis sinkron - tanpa memblokir utas utama, tentu saja). Lebih sedikit bicara, lebih banyak contoh:
/* These two snippets should do exactly the same thing */
// the js way
var url = 'file.txt';
fetch(url)
.then(function (data) {
data = "(" + data + ")";
return sendToServer(data);
}).then(function (response) {
console.log(response);
});
// synchronous-like way
var url = 'file.txt';
var response = sendToServer("(" + fetch(url) + ")");
console.log(response);
Apa cara paling elegan untuk mengkompilasinya kembali ke JS?
Kriteria, diurutkan berdasarkan kepentingan:
- Performa
- Kompatibilitas mundur
- Kode yang dapat dibaca (tidak terlalu penting)
Ada beberapa cara yang mungkin untuk mengimplementasikannya, ketiganya muncul di pikiran saya:
Menggunakan Janji:
f(); a( b() );
akan berubah menjadif().then(function(){ return b() }).then(function(x){ a(x) });
- pro: relatif mudah diimplementasikan, polyfillable kembali ke ES3
- kontra: membuat fungsi baru dan instance Proxy untuk setiap panggilan fungsi
-
f(); a( b() );
akan berubah menjadiyield f(); tmp = yield b(); yield a( tmp );
- pro: javascript lebih bagus
- kontra: membuat proxy, generator dan iterator pada setiap langkah, juga tidak bisa diisi polyfillable
- EDIT: sebenarnya mereka bisa diisi dengan polyfillable menggunakan recompiler lain (mis. Regenerator )
Menggunakan XMLHttpRequest sinkron:
- meminta skrip server yang menunggu hingga panggilan lain dari tempat lain dalam kode
- pro: de facto tidak ada perubahan dalam kode, super mudah diimplementasikan
- kontra: memerlukan skrip server (=> tanpa portabilitas, khusus browser); selanjutnya, XMLHttpRequest sinkron memblokir utas sehingga tidak berfungsi sama sekali
- EDIT: Ini sebenarnya akan bekerja di dalam Pekerja
Masalah utama adalah bahwa seseorang tidak dapat mengetahui apakah suatu fungsi tidak sinkron sampai runtime. Itu menghasilkan dua solusi yang setidaknya bekerja jauh lebih lambat daripada JS murni. Jadi saya bertanya:
Apakah ada cara yang lebih baik untuk diterapkan?
Dari jawaban:
Menunggu kata kunci (@ MI3Guy)
- C # way (mana yang bagus !)
- memperkenalkan kata kunci baru (yang dapat disamarkan sebagai fungsi (warga negara kelas 1) yang mis. melempar jika programmer mencoba untuk meneruskannya sebagai argumen)
- Bagaimana cara mengetahui fungsi itu asinkron? Tidak ada kata kunci lain!
- Setiap fungsi yang mengandung
await
kata kunci menjadi tidak sinkron? - Ketika kode sampai
await
, itu mengembalikan janji? Lain memperlakukan sebagai fungsi biasa?
- Setiap fungsi yang mengandung
f(); a( b() );
akan berubah menjadi f().then(b).then(a);
Anda tidak menyertakan fungsi.
synchronously (without blocking the thread, of course)
Anda tetap menggunakan kata itu. Saya tidak berpikir itu berarti apa yang Anda pikirkan artinya, karena secara serempak berarti "memblokir utas".