Saya ingin mengawali dengan mengatakan bahwa saya telah melihat banyak pertanyaan stackoverflow mengenai topik ini, tetapi saya belum menemukan 'duplikat' apa pun karena tidak ada yang berisi solusi yang akan menyelesaikan kasus khusus ini.

Saya terutama melihat Bagaimana cara mengembalikan respons dari panggilan asinkron?, dan bagian 'Janji dengan async/menunggu' akan berfungsi di dalam fungsi asinkron, tetapi fungsi yang saya kerjakan tidak asinkron dan merupakan bagian dari basis kode yang ada yang saya bisa' t berubah dengan mudah. Saya tidak akan dapat mengubah fungsi menjadi async.

Bagian tentang panggilan balik juga tidak akan berfungsi, yang dijelaskan lebih lanjut di bawah. Bagaimanapun, saya akan melompat ke pertanyaan saya:

Saya sedang mengedit fungsi (fungsi standar, bukan asinkron) dalam JavaScript dengan menambahkan panggilan fungsi asinkron. Saya ingin menunggu sampai panggilan async selesai sebelum saya kembali dari fungsi (karena hasil dari panggilan async perlu dimasukkan dalam nilai pengembalian). Bagaimana saya melakukannya?

Saya melihat ke dalam menggunakan panggilan balik, yang memungkinkan saya untuk menulis kode yang dijamin hanya berjalan setelah panggilan async selesai. Namun, ini tidak akan mengganggu aliran program dalam fungsi asli, dan fungsi asli masih dapat kembali sebelum panggilan balik dijalankan. Panggilan balik akan memungkinkan saya untuk menjalankan sesuatu secara berurutan setelah fungsi async, tetapi itu tidak akan memungkinkan saya untuk menunggu panggilan asinkron selesai pada tingkat tertinggi.

Contoh kode, yang tidak akan mengembalikan hasil yang diinginkan:

function getPlayers() {
    ... other code ...

    let outfieldPlayers = asyncGetOutfieldPlayersCall()

    ... other code ...

    allPlayers.add(outfieldPlayers)

    return allPlayers  // the returned value may or may not include outfield players
}

Masalah sebenarnya yang saya hadapi sedikit lebih rumit - saya memanggil fungsi async di setiap iterasi dari for loop, dan harus menunggu sampai semua panggilan selesai sebelum kembali. Tapi, saya pikir jika saya bisa menyelesaikan masalah yang lebih sederhana ini, saya bisa menyelesaikan masalah dengan for loop.

5
Bob Dole 23 April 2020, 03:31

2 jawaban

Jawaban Terbaik

Sayangnya, sangat tidak mungkin untuk menunggu kode async secara sinkron. Ini karena tidak ada threading di JS (sebagian besar runtime JS, tetapi beberapa adalah). Jadi kodenya sinkron atau asinkron.

Kode asinkron dimungkinkan karena perulangan peristiwa. Loop peristiwa adalah bagian dari runtime javascript. Ia bekerja dengan menyimpan setumpuk fungsi panggilan balik yang berjalan saat events memicunya - biasanya event timeout (yang dapat Anda atur dengan setTimeout()) atau event IO (yang terjadi saat Anda membuat disk atau permintaan HTTP, atau pada interaksi pengguna). Namun, callback ini hanya berjalan bila tidak ada kode lain yang berjalan, jadi hanya saat program tidak aktif dan semua fungsi telah kembali.

Ini berarti bahwa teknik seperti "spin loop" (di mana Anda hanya menjalankan loop sampai kondisi diubah oleh thread lain) yang bekerja di lingkungan berulir tidak berfungsi karena kode async tidak akan berjalan sampai putaran spin selesai.

Info Lebih Lanjut: https://medium.com/front-end -weekly/javascript-event-loop-explained-4cd26af121d4

2
Garrett Motzner 23 April 2020, 01:01

Jika Anda menggunakan NodeJS, ini dimungkinkan melalui execSync.

Ini mengharuskan Anda untuk menempatkan kode asinkron Anda di file terpisah, menelurkan proses terpisah menggunakan execSync, yang akan menunggu hingga keluar.

Misalnya, pertimbangkan fungsi async berikut yang mencetak array.

// task.js

(async function() {
    await new Promise((resolve) => setTimeout(() => {
        console.log(JSON.stringify([3,4,5]));

        resolve();
    }, 1000));
})();

Sekarang, Anda dapat memanggil ini dari proses utama Anda:

function asyncGetOutfieldPlayersCall() {
    const execSync = require('child_process').execSync;

    return JSON.parse(execSync("node task.js"));
}

function getPlayers() {
    let allPlayers = [1,2];
    // ... other code ...

    let outfieldPlayers = asyncGetOutfieldPlayersCall();

    // ... other code ...

    allPlayers = allPlayers.concat(outfieldPlayers)

    return allPlayers;
}
0
dinesh ygv 1 Agustus 2020, 09:51