#javascript #node.js #module #async-await #puppeteer
#javascript #node.js #модуль #async-await #кукловод
Вопрос:
У меня есть асинхронная функция, которая принимает список URL-адресов в качестве значения из проанализированного CSV-файла. Внутри этой функции я использую puppeteer для запуска страницы и перехода по каждому URL. У меня есть две функции — одна для загрузки ресурсов, а другая для проверки, был ли загружен ресурс.
- Я хотел бы сначала запустить scriptDownload(), а после завершения его выполнения запустить функцию NetworkProfile() .
- Я также хотел бы знать, можно ли выделить эти функции в отдельный файл и применить функциональность экспорта и импорта модулей.
Я не инициализировал функции в прилагаемом коде.
Кроме того, будет несколько асинхронных команд mongodb, которые будут добавлены позже в NetworkProfile() .
Я пытался использовать .then, но ничего не вышло. Всегда NetworkProfile() запускается перед scriptDownload()
Также пробовал экспортировать эти функции как отдельные модули, но в результате ошибка- страница- неопознанная ссылка
const puppeteer = require('puppeteer');
var fse = require('fs-extra');
var Papa= require("papaparse");
const path = require('path');
var scr = require('./scripts');
async function scripts(x){
const browser = await puppeteer.launch({
headless: true,
args: ['--enable-features=NetworkService'],
ignoreHTTPSErrors:true
});
const page = await browser.newPage();
const client = await page.target().createCDPSession();
await client.send('Network.enable');
await client.send('Network.clearBrowserCache');
await client.send('Runtime.enable');
await client.send('Debugger.enable');
async function scriptDownload() {
page.on('response', async resp => {
const url = new URL(page.url()).host;
const url1 = resp.request().url();
var url2 = path.basename(url1);
url2 = url2.replace(/?/g, 'amp;q');
const isScript = resp.request().resourceType() === 'script';
const isCSS = resp.request().resourceType() === 'stylesheet';
const isXHR = resp.request().resourceType() === 'xhr';
if (isScript) {
let filePath = path.resolve(`./Responses/${url}/js/${url2}.js`);
await fse.outputFile(filePath, await resp.text());
console.log('Scripts Downloaded');
}
if (isCSS) {
let filePath = path.resolve(`./Responses/${url}/css/${url2}.css`);
await fse.outputFileSync(filePath, await resp.text());
console.log('CSS Downloaded');
}
if (isXHR) {
let filePath = path.resolve(`./Responses/${url}/xhr/${url2}.xhr`);
await fse.outputFileSync(filePath, await resp.text());
console.log('XHR Downloaded');
}
});
}
//network domian
async function networkProfile() {
client.on('Network.requestWillBeSent', parameters => {
const request_url = parameters.request.url;
var reqname = path.basename(request_url);
var reqnamereg = reqname.replace(/?/g, 'amp;q');
const urlloc = new URL(page.url()).host;
try {
/**************************Check if file exists********************************************************** */
const jsFilePath = path.resolve(`./Responses/${urlloc}/js/${reqnamereg}.js`);
const jsPath = path.resolve(`./Responses/${urlloc}/js/${reqnamereg}`);
var locStorage = "null";
async function localjs(f) {
const existsjs = await fse.pathExists(f)
if (existsjs == true) {
locStorage = jsPath;
console.log(urlloc, reqnamereg, existsjs);
}
else {
locStorage = 'Js does not exist';
console.log(urlloc, reqnamereg, existsjs);
}
}
async function local(f) {
const exists = await fse.pathExists(f)
if (exists == true) {
locStorage = jsFilePath;
console.log(urlloc, reqname, exists);
}
else {
locStorage = 'File does not exist';
console.log(urlloc, reqname, exists);
}
}
if (reqname.endsWith('.js') == 'true') {
localjs(jsPath)
}
else {
local(jsFilePath)
}
} catch (error) {
console.log(error);
}
});
}
for (var j = 0; j < x.length; j ){
try{
await page.goto('https://www.' x[j][1], { waitUntil: 'load' });
const url = new URL(page.url()).host;
let filePathhtml = path.resolve(`./Responses/${url}/html/${url}.html`);
await fse.outputFileSync(filePathhtml, await page.content());
}
catch(error){
if(error==='net::ERR_CONNECTION_TIMED_OUT'){
}
}
}
setTimeout(async () => {
await page.close();
await browser.close();
}, 60000 * 2);
}
file = fse.createReadStream(__dirname '/test.csv', 'utf8')
function parseData(file, callBack) {
Papa.parse(file, {
delimiter: "", // auto-detect
newline: "", // auto-detect
header: false,
download: true,
complete: function(results) {
callBack(results.data);
}
});
}
parseData(file, scripts);
Ожидаемый результат будет
Загруженные скрипты
CSS загружен
…
…
…
url, reqname, true(для скриптов) false в противном случае
Ответ №1:
просто поместите их в разные функции и передайте им параметры
async function scriptx(){
await scriptDownload(page);
await networkProfile(client);
}
async function scriptDownload(page){
}
async function networkProfile(client){
}
но я не думаю, что вы делаете это правильно, вы пытаетесь проверить событие внутри функции, которая также должна быть вызвана
Комментарии:
1. Я попробовал это, но не уверен, сработает ли это, потому что, если я помещу функции снаружи, возникнет ошибка ссылки. Например, если я помещу scriptDownload снаружи, страница в page.on не определена. Есть ли что-то еще, например, ожидание завершения события в scriptDownload, а затем выполнение другой функции
2. вы должны передать
page
в качестве аргументаscriptDownload
функции … следовательноscriptDownload(page)