Saya memiliki Janji JavaScript murni (implementasi bawaan atau poli-isi):
var promise = new Promise(function (resolve, reject) { /* ... */ });
Dari spesifikasinya , Janji dapat menjadi salah satu dari:
- 'diselesaikan' dan 'diselesaikan'
- 'diselesaikan' dan 'ditolak'
- 'tertunda'
Saya memiliki kasus penggunaan di mana saya ingin menginterogasi Janji secara serempak dan menentukan:
Apakah Janji sudah terpenuhi?
jika demikian, apakah Janji itu terselesaikan?
Saya tahu bahwa saya dapat menggunakan #then()
untuk menjadwalkan pekerjaan yang akan dilakukan secara tidak sinkron setelah kondisi perubahan Janji. Saya TIDAK bertanya bagaimana melakukan ini.
Pertanyaan ini secara khusus tentang interogasi sinkron dari negara Janji . Bagaimana saya bisa mencapai ini?
javascript
promise
es6-promise
Jokeyrhyme
sumber
sumber
var promiseStatus = NEW_PRIVATE("Promise#status");
,PromiseSet
berfungsi diSET_PRIVATE(promise, promiseStatus, status);
console.log(Promise.new((resolve, reject) => {})
=>Promise { <pending> }
Jawaban:
Tidak ada API inspeksi sinkron seperti itu untuk janji JavaScript asli. Tidak mungkin melakukan ini dengan janji-janji asli. Spesifikasi tidak menentukan metode seperti itu.
Perpustakaan Userland dapat melakukan ini, dan jika Anda menargetkan mesin tertentu (seperti v8) dan memiliki akses ke kode platform (yaitu, Anda dapat menulis kode dalam inti ) maka Anda dapat menggunakan alat khusus (seperti simbol pribadi) untuk mencapai ini . Itu super spesifik dan bukan di userland.
sumber
.any
dan membuat kesalahan karena Mark bersikeras. Untuk satu,Promise.race([])
adalah janji yang tertunda selamanya (dan bukan kesalahan), Anda biasanya menginginkan janji sukses pertama dan bukan hanya janji pertama. Bagaimanapun, itu tidak benar-benar relevan dengan pertanyaan yang diajukan - OP bertanya tentang inspeksi sinkron dan bukan tentang.race
dan banyak kekurangannya.MakeQueryablePromise(Promise.resolve(3)).isResolved
salah tetapi janji itu jelas-jelas diselesaikan. Belum lagi jawaban itu juga menggunakan istilah "diselesaikan" dan "terpenuhi" salah. Untuk melakukan itu, Anda dapat menambahkan.then
handler sendiri - yang benar-benar melenceng dari titik pemeriksaan sinkron.janji-status-async berhasil . Itu async tetapi tidak digunakan
then
untuk menunggu janji untuk diselesaikan.sumber
Tidak, tidak ada API sinkronisasi, tapi ini versi async saya
promiseState
(dengan bantuan dari @Matthijs):sumber
Promise.race([ Promise.resolve(p).then(() => "fulfilled", () => "rejected"), Promise.resolve().then(() => "pending") ]);
Meskipun ini tampaknya lebih aman bagi saya:const t = {}; return Promise.race([p,t]).then(v => v === t ? "pending" : "fulfilled", () => "rejected")
dan menghindari membuat janji-janji tambahan yang bertahan selama p yang asli tertunda.Anda dapat membuat balapan dengan Promise.resolve
Ini tidak sinkron tetapi terjadi sekarang
Sebuah skrip kecil untuk menguji dan memahami maknanya secara asinkron
hasil dengan penundaan (0) (beri komentar pada saat penundaan)
dan hasil tes ini dengan firefox (chrome keep the order)
janjiState membuat .race dan .then: Level 2
sumber
'a value that p should not return'
, gunakan SimbolSymbol
akan menjadi nilai unik, oleh karena itu Anda tidak perlu menebak "nilai [...] apa yang tidak boleh dikembalikan." Namun, referensi ke objek tertentu akan berfungsi juga.Anda dapat menggunakan peretasan (jelek) di Node.js hingga metode asli ditawarkan:
sumber
Promise.prototype.isPending = function(){ return util.inspect(this).indexOf("<pending>")>-1; }
process.binding('util').getPromiseDetails
Promise.resolve('<pending>')
.dalam simpul, katakanlah internal tidak berdokumen
process.binding('util').getPromiseDetails(promise)
sumber
Diperbarui: 2019
Bluebird.js menawarkan ini: http://bluebirdjs.com/docs/api/isfulfilled.html
Jika Anda lebih suka membuat bungkus Anda sendiri, berikut adalah blog yang bagus .
Karena JavaScript adalah single-threaded, sulit untuk menemukan kasus penggunaan yang cukup umum untuk membenarkan memasukkan ini ke dalam spesifikasi. Tempat terbaik untuk mengetahui apakah janji terselesaikan ada di .then (). Menguji apakah Janji telah dipenuhi akan membuat sebuah polling loop yang kemungkinan besar adalah arah yang salah.
async / await adalah konstruk yang bagus jika Anda ingin memberikan kode async secara sinkron.
Panggilan berguna lainnya adalah Promise.all ()
Ketika saya pertama kali meraih jawaban ini, itulah use case yang saya cari.
sumber
Anda dapat memenuhi janji Anda dengan cara ini
sumber
.then
selalu mengeksekusi OP tidak sinkron yang ingin memeriksa janji pada gilirannya yang sama tidak akan mendapatkan hasil yang benar di sini. Catatan OP bertanya secara spesifik tentang inspeksi sinkron dan menyebutkan bahwa mereka sudah tahu tentang inspeksi asinkron.Memang sangat menjengkelkan bahwa fungsi dasar ini tidak ada. Jika Anda menggunakan node.js maka saya tahu dua solusi, tak satu pun dari mereka sangat cantik. Kedua cuplikan di bawah ini menerapkan API yang sama:
Sepertinya tidak ada cara untuk membedakan kedua negara janji terakhir menggunakan salah satu trik.
1. Gunakan API debug V8
Ini adalah trik yang sama yang
util.inspect
digunakan.2. Jalankan microtasks secara sinkron
Ini menghindari API debug, tetapi memiliki semantik yang menakutkan dengan menyebabkan semua mikrotasks dan
process.nextTick
callback yang tertunda dijalankan secara serempak. Ini juga memiliki efek samping mencegah kesalahan "penolakan janji yang tidak tertangani" pernah dipicu untuk janji yang diinspeksi.sumber
process._tickCallback
(atau bahkan% RunMicrotick) - ini akan secara acak merusak hal-hal dalam kode Anda. Saya mati-matian mencoba membuatnya bekerja (untuk timer palsu dalam fungsi async, kebanyakan) dan itu tidak pernah cukup stabil dari sisi Node. Saya agak menyerah mengerjakannya. API mirror debug V8 sepenuhnya sesuai di sini.DeprecationWarning: DebugContext has been deprecated and will be removed in a future version.
:( Sepertinya V8 menghapusnyaprocess.binding('util').getPromiseDetails( promise )
pengembalian[ 0, ]
untuk menunggu,[ 1, value ]
untuk dipenuhi, dan[ 2, value ]
untuk ditolak.Peringatan: Metode ini menggunakan internal Node.js yang tidak berdokumen dan dapat diubah tanpa peringatan.
Di Node, Anda dapat secara sinkron menentukan status janji menggunakan
process.binding('util').getPromiseDetails(/* promise */);
.Ini akan mengembalikan:
[0, ]
untuk menunggu,[1, /* value */]
untuk dipenuhi, atau[2, /* value */]
untuk ditolak.Membungkus ini ke dalam fungsi pembantu:
sumber
jest
(yang merupakan satu-satunya tempat saya tertarik, sungguh). Fungsi itu ada, tetapi sepertinya selalu kembaliundefined
. Bagaimana saya mencari tahu apa yang salah?mocha
; tidak pernah mencobanya denganjest
sekalipun. Mungkin memulai pertanyaan baru yang menghubungkan di sini dan termasuk versi Node.js Anda dan jugajest
versi?Promise
bahwa saya hanya menggunakan untuk menguji hal-hal yang harus terjadi ketikaPromise
sedang tertunda, tapi saya pikir selama apa yang saya tulis, bekerja, maka tidak perlu untuk menguji bahwa selain apa yang bergantung padanya.apa yang dapat Anda lakukan, adalah menggunakan variabel untuk menyimpan keadaan, secara manual mengatur keadaan ke variabel itu, dan memeriksa variabel itu.
tentu saja, ini berarti Anda harus memiliki akses ke kode janji yang asli. Jika tidak, maka Anda dapat melakukan:
Solusi saya lebih banyak coding, tapi saya pikir Anda mungkin tidak perlu melakukan ini untuk setiap janji yang Anda gunakan.
sumber
Pada Node.js versi 8, Anda sekarang dapat menggunakan paket inspeksi bijak untuk secara sinkron memeriksa janji-janji asli (tanpa peretasan berbahaya).
sumber
Anda dapat menambahkan metode ke Promise.prototype. Ini terlihat seperti ini:
Diedit: Solusi pertama tidak berfungsi sebagaimana mestinya, seperti sebagian besar jawaban di sini. Ini mengembalikan "pending" sampai fungsi asinkron ".then" dipanggil, yang tidak terjadi segera. (Hal yang sama adalah tentang solusi menggunakan Promise.race). Solusi kedua saya memecahkan masalah ini.
Anda dapat menggunakannya di Janji apa pun. Sebagai contoh:
Solusi kedua (dan benar):
Dan gunakan itu:
Perhatikan : Dalam solusi ini Anda tidak harus menggunakan operator "baru".
sumber
Ini adalah versi QueryablePromise yang lebih sempurna, memungkinkan kemampuan untuk rantai kemudian dan menangkap setelah tekad pertama dan segera menyelesaikan atau menolak untuk menjaga api tetap konsisten dengan Janji asli.
sumber
await
penggunaan untuk jawaban @ jib , dengan prototyping idiomatik.perhatikan bahwa fungsi async ini menjalankan "hampir" segera seperti fungsi yang disinkronkan (atau sebenarnya mungkin secara instan).
sumber
2019:
Cara sederhana untuk melakukan itu seperti yang saya tahu adalah
thenable
, pembungkus super tipis di sekitar janji atau pekerjaan async.sumber
Anda dapat membuat subclass Anda sendiri, katakanlah
QueryablePromise
, dengan mewarisi dariPromise
kelas yang tersedia secara asli , instance yang akan memilikistatus
properti yang tersedia di dalamnya yang dapat Anda gunakan untuk menanyakan status objek janji secara serempak . Implementasinya dapat dilihat di bawah atau merujuk ini untuk penjelasan yang lebih baik.sumber
fetch
akan mengembalikan janji asli. Bagaimana kelas Anda membantu hal itu?const queryableFetch = new QueryablePromise((resolve, reject) => {fetch(/.../).then((data) => resolve(data)) })
? Atau, apakah ada masalah dengan itu? : /, err => reject(err)
sebagai argumen keduathen
atau tidak akan menyebarkan kesalahan dengan benar (di antara alasan itu dianggap sebagai konstruktor janji anti-pola ). Itu tidak benar-benar sinkron (misalnya tidak akan mendeteksi janji yang sudah diselesaikan), tetapi mungkin berguna dalam kasus di mana Anda tidak mengontrol penelepon dan jawabannya diperlukan segera.Ada lagi yang elegan cara & Hacky memeriksa apakah janji masih tertunda hanya dengan mengubah seluruh objek string dan memeriksa dengan bantuan memeriksa seperti ini:
util.inspect(myPromise).includes("pending")
.Diuji pada Node.js 8,9,10,11,12,13
Ini contoh lengkapnya
Hasil:
sumber
Jika Anda menggunakan ES7 eksperimental, Anda dapat menggunakan async untuk dengan mudah membungkus janji yang ingin Anda dengarkan.
sumber
Saya telah menulis paket npm kecil, nilai janji, yang menyediakan pembungkus janji dengan
resolved
bendera:https://www.npmjs.com/package/promise-value
Ini juga memberikan akses sinkron ke nilai janji (atau kesalahan). Ini tidak mengubah objek Janji itu sendiri, mengikuti bungkus daripada memperpanjang pola.
sumber
Ini adalah pertanyaan lama tetapi saya mencoba melakukan hal serupa. Saya perlu menjaga agar pekerja tetap berjalan. Mereka terstruktur dalam sebuah janji. Saya perlu memindai dan melihat apakah mereka diselesaikan, ditolak atau masih tertunda. Jika diselesaikan, saya perlu nilainya, jika ditolak melakukan sesuatu untuk memperbaiki masalah atau menunggu keputusan. Jika diselesaikan atau ditolak, saya harus memulai tugas lain untuk terus berjalan. Saya tidak dapat menemukan cara untuk melakukannya dengan Promise.all atau Promise.race karena saya terus bekerja janji dalam array dan tidak dapat menemukan cara untuk menghapusnya. Jadi saya membuat pekerja yang melakukan trik
Saya membutuhkan fungsi generator janji yang mengembalikan janji yang menyelesaikan atau menolak seperlunya. Ini disebut oleh fungsi yang mengatur kerangka kerja untuk mengetahui apa yang dilakukan janji.
Dalam kode di bawah ini generator hanya mengembalikan janji berdasarkan setTimeout.
Ini dia
doWork mengembalikan objek yang berisi janji dan statusnya serta nilai yang dikembalikan.
Kode berikut menjalankan loop yang menguji negara dan membuat pekerja baru agar tetap di 3 pekerja berjalan.
Diuji dalam node.js
BTW Bukan dalam jawaban ini tetapi pada topik lain yang serupa, saya BENCI ketika seseorang mengatakan "Anda tidak mengerti" atau "itu bukan cara kerjanya" Saya biasanya menganggap penanya tahu apa yang mereka inginkan. Menyarankan cara yang lebih baik itu bagus. Penjelasan yang sabar tentang bagaimana janji bekerja juga akan baik.
sumber
Saya menemukan solusi ini sederhana dan memungkinkan saya untuk terus menggunakan janji-janji asli tetapi menambahkan pemeriksaan sinkron yang berguna. Saya juga tidak perlu menarik seluruh perpustakaan janji.
CAVEAT: Ini hanya berfungsi jika ada semacam jeda di utas eksekusi saat ini untuk memungkinkan janji untuk dieksekusi SEBELUM memeriksa konstruksi sinkron. Itu membuat kegunaan ini lebih terbatas daripada yang saya pikirkan - masih berguna untuk kasus penggunaan saya (Terima kasih Benjamin Gruenbaum untuk menunjukkan ini)
Dari https://ourcodeworld.com/articles/read/317/how-to-check-if-a-javascript-promise-has-been-fulfilled-rejected-or-resolved yang mendasarkan jawaban mereka pada apakah ada cara untuk memberi tahu apakah janji ES6 dipenuhi / ditolak / diselesaikan?
sumber
MakeQueryablePromise(Promise.resolve(3)).isResolved
salah tetapi janji itu jelas-jelas terselesaikan. Belum lagi jawaban itu juga menggunakan istilah "diselesaikan" dan "terpenuhi" salah. Untuk melakukan itu, Anda dapat menambahkan.then
handler sendiri - yang benar-benar melenceng dari titik pemeriksaan sinkron.let wrappedPromise = MakeQueryablePromise(Promise.resolve(3)); setTimeout(function() {console.log(wrappedPromise.isFulfilled())}, 1);
Yang selama Anda melakukan itu, ini bekerja dengan baik. Tetapi Anda harus memahami fakta itu agar ini berguna. Saya akan memperbarui deskripsi dengan peringatan itu. Saya juga setuju bahwa penamaan fungsi bisa lebih baik / lebih idiomatis.then
janji asli dan mencapai hal yang sama karena itu tetap tidak sinkron. Ada caraprocess.binding('util').getPromiseDetails
yang sepertinya berhasil tetapi menggunakan API pribadi