Как использовать обещание для сложения нескольких значений?

#javascript #promise #es6-promise

Вопрос:

Я хочу прочитать три txt-файла и сложить текстовые результаты, возвращаемые из realFile(), ниже приведен мой код, используемый для обратного вызова. Как мы используем Promise и .then() для добавления всего текста?

 fs.readFile('./a.txt', 'utf8', (err, data) => {
   if(err) console.log(err)
   fs.readFile('./b.txt', 'utf8', (err, newData) => {
     if(err) console.log(err)
     fs.readFile('./c.txt', 'utf8',(err, newestData) => {
       if (err) console.log(err)
       console.log(data newData newestData)
     })
   })
})
 

Комментарии:

1. Узел предоставляет версию fs модуля на основе обещаний; используйте ее вместе с Promise.all

2. Вы хотите остановиться на ошибке или продолжить?

Ответ №1:

Вы можете использовать fs.promises API для получения обещанных методов.

Затем просто сделайте Promise.all :

 const p1 = fs.promises.readFile('./a.txt', 'utf8')
const p2 = fs.promises.readFile('./b.txt', 'utf8')
const p3 = fs.promises.readFile('./c.txt', 'utf8')

Promise.all([p1, p2, p3])
  .then(([v1, v2, v3]) => console.log(v1   v2   v3))
  .catch(e => console.error(e))
 

Вы также можете избежать повторения с массивами:

 const files = ['./a.txt', './b.txt', './c.txt']

Promise.all(
  files.map(file => fs.promises.readFile(file, 'utf8'))
)
  .then(([v1, v2, v3]) => console.log(v1   v2   v3))
  .catch(e => console.error(e))
 

Если вы действительно ищете что-то с несколькими .then() буквами s, вы могли бы сделать это таким образом (хотя это не намного лучше, чем ваш первоначальный обратный вызов).:

 fs.promises.readFile('./a.txt', 'utf8').then(v1 => 
  fs.promises.readFile('./b.txt', 'utf8').then(v2 => 
    fs.promises.readFile('./c.txt', 'utf8').then(v3 => 
      console.log(v1 v2 v3)
    )
  )
)
  .catch(e => console.error(e))
 

Комментарии:

1. Я хочу показать цепочку .then() для ее реализации, есть ли способ использовать три раза .then()?

2. Зачем тебе это нужно? Чего еще вы хотите достичь с помощью этого, что не работает таким образом?

3. @LeeAlex p1.then(file1Data => p2.then(file2Data => [file1Data, file2Data])).then(arr => p3.then(file3Data => [...arr, file3Data])).then(dataArr => { ... }).catch(...)

4. @FZs Это работает, но я просто хочу посмотреть, как использовать только .than() для сравнения с помощью обратного вызова

5. @LeeAlex Я добавил решение, использующее только .then() s, но реальная сила обещаний заключается в их составляемости, поэтому вам следует сравнить свой код с другими решениями в моем ответе.

Ответ №2:

Проверьте фрагмент кода ниже, я добавил логику как для обещаний, так и для асинхронного/ожидания

 

    const fs = require('fs');
    const util = require("util");

    const readFile = util.promisify(fs.readFile);

    // return promise which can resolved later
    // data is array of promise in same order of 
    let data = Promise.all([
        readFile('file.txt', 'utf8'),
        readFile('file.txt', 'utf8'),
        readFile('file.txt', 'utf8')
    ])

    data.then(([data1, data2, data3]) => {
        console.log(data1, data2, data3)
    }).catch(error => console.log(error))

 

Мы можем достичь этого с помощью async/await даже с простым синтаксисом

 

    const fetchData = async () => {
        const data1 = await readFile('file.txt', 'utf8');
        const data2 = await readFile('file.txt', 'utf8');
        const data3 = await readFile('file.txt', 'utf8');
        console.log(data1, data2, data3);
    }

    fetchData();