#javascript #node.js #asynchronous #promise
#javascript #node.js #асинхронный #обещание
Вопрос:
Я хочу прочитать файл с помощью javascript. Этот файл должен быть загружен первым и доступен не сразу. Это означает, что если доступ к этому файлу с помощью ReadFile() завершается неудачно и заканчивается в блоке catch, то это действие следует повторить.
const fse = require('fs-extra')
let retries = 0
function read_a_file(path) {
return fse.readFile(path)
.catch(error => {
if (retries < 5) {
retries
console.log('Retry', retries)
setTimeout(() => read_a_file(path), 1000);
} else {
console.log(error.message)
}
})
}
read_a_file('path/to/file').then(content => {
console.log('Content:', content)
})
Вывод этой функции:
Retry 1
Content: undefined
Retry 2
Retry 3
Retry 4
Retry 5
ENOENT: no such file or directory, open 'path/to/file'
Теперь я бы ожидал, что содержимое (в данном случае неопределенное) будет выводиться в конце всех попыток. Почему он выдается перед первым повторением?
Комментарии:
1. Я бы предположил, что это возврат из первого обещания.
2.
setTimeout(() => read_a_file(path), 1000);
создает новое обещание безthen
Ответ №1:
Вы создаете новые обещания в setTimeout, которые не имеют ничего общего с первоначальным обещанием, которое вы вернули.
Я бы создал обещание и вернул его. ReadFile вызовет разрешение или отклонение этого обещания.
const fse = require('fs-extra')
function read_a_file(path) {
let retries = 0
const readFile(resolve, reject) {
fse.readFile(path)
.then(resolve)
.catch(error => {
if (retries < 5) {
retries
console.log('Retry', retries)
setTimeout(() => readFile(resolve, reject), 1000);
} else {
console.log(error.message)
reject(error);
}
})
}
return new Promise((resolve, reject) => readFile(resolve, reject));
}
read_a_file('path/to/file')
.then(content => {
console.log('Content:', content)
})
.catch(e => {
console.log(e);
})
Ответ №2:
Вы используете .then
только в первом вызове, поэтому функция регистрации содержимого будет работать только один раз.
read_a_file('path/to/file').then(content => {
console.log('Content:', content)
})
Ваш другой вызов функции заключается setTimeout(() => read_a_file(path), 1000);
в том, что если вы добавите a .then
после этого, он также зарегистрирует его после разрешения других обещаний. Тогда вы получите 5 таких выходных данных.