Sepertinya ada beberapa kebingungan di sini tentang cara menggunakan Promises dengan benar, di beberapa level.
Callback dan Promise digunakan secara tidak benar
Jika fungsi seharusnya menerima panggilan balik, jangan kembalikan Janji. Jika fungsi seharusnya mengembalikan Janji, gunakan panggilan balik yang diberikan oleh Janji:
const transactionSession = await mongoose.startSession()
await transactionSession.withTransaction( (tSession) => {
return new Promise( (resolve, reject) => {
//using Node-style callback
doSomethingAsync( (err, testData) => {
if(err) {
reject(err);
} else {
resolve(testData); //this is the equivalent of cb(null, "Any test data")
}
});
})
Mari kita lihat ini lebih detail:
return new Promise( (resolve, reject) => {
Ini membuat Janji baru, dan Janji memberi Anda dua panggilan balik untuk digunakan. resolve
adalah panggilan balik untuk menunjukkan keberhasilan. Anda memberikannya objek yang ingin Anda kembalikan. Perhatikan bahwa saya telah menghapus async
kata kunci (lebih lanjut tentang ini nanti).
Misalnya:
const a = new Promise( (resolve, reject) => resolve(5) );
a.then( (result) => result == 5 ); //true
(err, testData) => {
Fungsi ini digunakan untuk memetakan gaya Node cb(err, result)
ke panggilan balik Promise.
Coba/tangkap digunakan secara tidak benar.
Coba/tangkap hanya dapat digunakan untuk pernyataan sinkron. Mari kita bandingkan panggilan sinkron, gaya Node (yaitu cb(err, result)
) panggilan balik asinkron, Janji, dan menggunakan menunggu:
- Sinkron:
try {
let a = doSomethingSync();
} catch(err) {
handle(err);
}
- Asinkron:
doSomethingAsync( (err, result) => {
if (err) {
handle(err);
} else {
let a = result;
}
});
- Janji:
doSomethingPromisified()
.then( (result) => {
let a = result;
})
.catch( (err) => {
handle(err);
});
- Tunggu. Await dapat digunakan dengan fungsi apa pun yang mengembalikan Promise, dan memungkinkan Anda menangani kode seolah-olah sinkron:
try {
let a = await doSomethingPromisified();
} catch(err) {
handle(err);
}
Info Tambahan
Promise.resolve()
Promise.resolve()
membuat Janji baru dan menyelesaikan Janji itu dengan nilai yang tidak ditentukan. Ini adalah singkatan dari:
new Promise( (resolve, reject) => resolve(undefined) );
Panggilan balik yang setara dengan ini adalah:
cb(err, undefined);
async
async
pergi dengan await
. Jika Anda menggunakan await
dalam suatu fungsi, fungsi itu harus dideklarasikan sebagai async
.
Sama seperti await
membuka bungkusan Janji (resolve
menjadi nilai, dan reject
menjadi pengecualian), async
membungkus kode menjadi Janji. Sebuah return value
pernyataan diterjemahkan ke dalam Promise.resolve(value)
, dan pengecualian yang dilemparkan throw e
diterjemahkan ke dalam Promise.reject(e)
.
Perhatikan kode berikut
async () => {
return doSomethingSync();
}
Kode di atas setara dengan ini:
() => {
const p = new Promise(resolve, reject);
try {
const value = doSomethingSync();
p.resolve(value);
} catch(e) {
p.reject(e);
}
return p;
}
Jika Anda memanggil salah satu fungsi di atas tanpa await
, Anda akan mendapatkan kembali Janji. Jika Anda await
salah satu dari mereka, Anda akan dikembalikan nilai, atau pengecualian akan dilemparkan.