JavaScript: повторите асинхронную функцию ReadFile()

#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 таких выходных данных.