Добрый день! Пытаюсь разобраться в основах асинхронной разработки под Node.js. Задача, которую я себе придумал, выглядит так: выкачать страницу по определенному адресу, затем сохранить ее, после этого распарсить и выделить нужную часть по шаблону (классы в html-коде), а выделенный кусок сохранить в отдельный файл.
Код выглядит так:
var rp = require('request-promise');
var fs = require('fs-extra'); // расширенный модуль для работы с файловой системой
let a = rp('https://somesite.com/')
.then((htmlString) => {
let path = './saved.html';
fs.outputFile(path, htmlString);
})
.then(() => console.log('HTML saved to file!')) // до этого момента отрабатывает нормально
.then(() => {
fs.readFile('./saved.html', 'utf8', function (error, data) {
if (error) {
console.log(error)
}
let start = data.indexOf('<div class="some-class">');
let finish = data.indexOf('<script class="some-another-class">');
console.log(start); // для отладки смотрю, нашлись ли вхождения
console.log(finish);
let htmlSubstring = data.substring(start, finish);
console.log(htmlSubstring.length); //смотрю, вырезалась ли нужная мне часть html
let parsed = './parsed.html';
fs.outputFile(parsed, htmlSubstring);
})
})
.then(() => console.log('HTML (parsed) saved to file!'))
.catch((err) => console.error(err));
Однако код работает неправильно: при первом прогоне, когда файл saved.html еще не создался, на этапе его чтения всё падает:
{ [Error: ENOENT: no such file or directory, open 'D:\git\tests\saved.html']
errno: -4058,
code: 'ENOENT',
syscall: 'open',
path: 'D:\\git\\tests\\saved.html' }
D:\git\tests\index.js:15
let start = data.indexOf('<div class="some-class">');
^
TypeError: Cannot read property 'indexOf' of undefined
at ReadFileContext.<anonymous> (D:\git\tests\index.js:15:30)
at ReadFileContext.callback (D:\git\tests\node_modules\graceful-fs\graceful-fs.js:90:16)
at FSReqCallback.readFileAfterOpen [as oncomplete] (fs.js:244:13)
Program exited with status code of 1.
При втором прогоне, когда файл уже скачан, код отрабатывает, но вывод все равно выглядит не так, как должен:
HTML saved to file!
HTML (parsed) saved to file!
25447
40883
15436
Program exited with status code of 0.
Вначале выводится сообщение из нижнего промиса, а только потом - из верхнего.
Почему так получается? Ведь по идее цепочка должна выполняться так: новый .then() вступает в действие только тогда, когда полностью отработал предыдущий. А у меня выходит так, что они работают параллельно, и понятно, что быстрее срабатывает вывод в консоль, а файловые операции медленнее.
Прошу сильно не пинать, асинхронный код в JS мне дается непросто.