typescript - Bagaimana untuk menyemak jika Laman Puppeteer sedang berada dalam keadaan navigasi?
Saya sedang menulis beberapa pembalut di atas Puppeteer. Saya mempunyai fungsi umum "klik", dan satu lagi fungsi "dapatkanHtml":
class Page {
....
async click(selector: string) {
await this.context.evaluate((querySelector, text) => {
const elem = document.querySelector(querySelector) as HTMLInputElement;
if (elem) {
elem.click();
}
}, selector);
}
async getHtml() {//
const html = await this.context.evaluate(() => {
return document.querySelector('html')?.innerHTML;
})
return html;
}
}
Seperti yang anda boleh lihat, fungsi click() hanya menerima querySelector, dan kemudian mengklik apa sahaja elemen yang dijumpai.
Masalahnya ialah, jika klik elemen ini menyebabkan navigasi, operasi seterusnya mungkin menghadapi ralat ini:
Konteks pelaksanaan telah dimusnahkan, kemungkinan besar kerana navigasi
Contohnya, jika kod klien melakukan sesuatu seperti ini:
const page = new Page(...)
...
await page.click('someSelector')//If this selector matches a link, navigation is triggered.
await page.getHtml()//Then there is an Error
Adakah cara untuk menyemak jika terdapat navigasi yang belum selesai, supaya saya boleh menunggu secara bersyarat untuknya, dalam pelbagai fungsi?
Saya tidak boleh hanya tungguUntukNavigasi secara lalai, di dalam fungsi klik, kerana ini akan menyebabkan kod tergantung, sekiranya tiada navigasi berlaku akibat klik tersebut.
Jawapan #1
2 Tahun Kemudian...
Saya mendarat di sini kerana saya mendapat Execution context was destroyed [...] selepas memanggil page.goto() dan seterusnya page.content().
ringkasan
// dirty hack to avoid blocking of 'page.waitForNavigation()'
await page.waitForSelector('html')
page.waitForSelector('html') akan segera diselesaikan jika tiada pengalihan seterusnya disebabkan oleh tetapan location.href atau History.pushState() dan menunggu (untuk satu pengalihan) sebaik sahaja navigasi berjaya.
- Mengapa ini berlaku?
Dalam kes saya, ia disebabkan oleh location.href yang ditetapkan selepas halaman dimuatkan. Dalam kes ini kandungan diminta apabila halaman sedang dinavigasi ke alamat baru.
- Kenapa tidak page.waitForNavigation()
page.waitForNavication() sentiasa menghalang sehingga navigasi berjaya. Sama seperti OP, saya tidak dapat menganggap bahawa navigasi sentiasa berlaku dan saya juga tidak dapat mengetahui bila ia berlaku sebelum ini. Saya ingin mengelakkan penghalangan yang tidak perlu jadi kaedah ini bukan pilihan yang sesuai.
- Kekurangan
Jika pelayan membalas dengan apa-apa selain daripada payload HTML yang sah, page.waitForSelector('html') akan terhalang dan akhirnya tamat masa, menyebabkan ralat.
Jawapan #2
Mungkin jalan penyelesaian seperti ini boleh membantu?
const [_, navigation] = await Promise.allSettled([
elem.click(),
page.waitForNavigation(),
]);
if (navigation.status === 'fulfilled') /* There was navigation. */;
else /* There was timeout, no navigation. */;
