Fs.writeFile в обещании, асинхронно-синхронный материал

Мне нужна помощь с моим кодом. Я новичок в Node.js и у меня много проблем с этим.

Что я пытаюсь сделать:

1) Получить. TXT с продуктами Amazon (ASIN);

2) Получить все продукты, используя пакет amazon-product-api;

3) Сохраните каждый продукт в файле .json.

Мой код не работает. Я думаю, что я запутался с этим асинхронно-синхронным материалом - помогите мне!

var amazon = require('amazon-product-api');
var fs = require('fs');

var client = amazon.createClient({
    awsId: "XXX",
    awsSecret: "XXX",
    awsTag: "888"
});

var array = fs.readFileSync('./test.txt').toString().split('\n');
for (var i = 1; i < array.length; i++) {
     var ASIN = array[i];

    return client.itemLookup({
            domain: 'webservices.amazon.de',
            responseGroup: 'Large',
            idType: 'ASIN',
            itemId: ASIN
        })
        .then(function(results) {
            fs.writeFile(ASIN + '.json', JSON.stringify(results), function(err) {
                if (err) {
                    console.log(err);
                } else {
                    console.log("JSON saved");
                }
            })

            return results;

        }).catch(function(err) {
            console.log(err);
        });
};

Ответ 1

Поскольку fs.writefile является традиционным асинхронным обратным вызовом - вам нужно следовать спецификации обещания и возвращать новое обещание, обертывая его обработчиком разрешения и отклонения следующим образом:

return new Promise(function(resolve, reject) {
    fs.writeFile("<filename.type>", data, '<file-encoding>', function(err) {
        if (err) reject(err);
        else resolve(data);
    });
});

Итак, в вашем коде вы будете использовать его так же, как сразу после вашего вызова .then()

 .then(function(results) {
    return new Promise(function(resolve, reject) {
            fs.writeFile(ASIN + '.json', JSON.stringify(results), function(err) {
               if (err) reject(err);
               else resolve(data);
            });
    });
  }).then(function(results) {
       console.log("results here: " + results)
  }).catch(function(err) {
       console.log("error here: " + err);
  });

Ответ 2

сказать

const util = require('util')
const fs_writeFile = util.promisify(fs.writeFile)

https://nodejs.org/api/util.html#util_util_promisify_original

это менее подвержено ошибкам, чем ответ с наибольшим количеством голосов

Ответ 3

По состоянию на 2019 год...

... правильный ответ - использовать async/await с собственным модулем fs Promises, включенным в узел. Обновите до Node.js 10 или 11 (уже поддерживается основными поставщиками облачных услуг) и сделайте следующее:

const fs = require('fs').promises;

// This must run inside a function marked 'async':
const file = await fs.readFile('filename.txt', 'utf8');
await fs.writeFile('filename.txt', 'test');

Не используйте сторонние пакеты и не пишите свои собственные обертки, которые больше не нужны.

Больше не экспериментально

До Узла 11.14.0 вы все равно получили бы предупреждение о том, что эта функция является экспериментальной, но она работает просто отлично, и это путь в будущем. Начиная с 11.14.0, эта функция больше не является экспериментальной и готова к производству.

Что делать, если я предпочитаю import а не require?

Это также работает, но только в версиях Node.js, где эта функция не помечена как экспериментальная.

import { promises as fs } from 'fs';

(async () => {
    await fs.writeFile('./test.txt', 'test', 'utf8');
})();

Ответ 4

Наконец, последний выпуск node.js v10.3.0 имеет изначально поддерживаемые обещания fs.

const fsPromises = require('fs').promises; // or require('fs/promises') in v10.0.0
fsPromises.writeFile(ASIN + '.json', JSON.stringify(results))
  .then(() => {
    console.log('JSON saved');
  })
  .catch(er => {
    console.log(er);
  });

Вы можете проверить официальную документацию для более подробной информации. https://nodejs.org/api/fs.html#fs_fs_promises_api

Ответ 5

Обновление Сентябрь 2017: fs-promise устарел в пользу fs-extra.


Я не использовал его, но вы можете посмотреть fs-promise. Это модуль node, который:

Проксирует все методы async fs, отображая их как Promises/A + compatible promises (когда, Q и т.д.). Пропускает все методы синхронизации через значения.

Ответ 6

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

const fs_writeFile = util.promisify(fs.writeFile)

fs_writeFile('message.txt', 'Hello Node.js')
    .catch((error) => {
        console.log(error)
    });

Ответ 7

Похоже, что fs.writeFile(...) сам теперь возвращает обещание при использовании библиотеки fs: const fs = require('fs'); ,

Когда я запускаю свой код fs.writeFile(tempFile, response.auioContent, 'binary') then возвращается часть кода.

.then(() => {
    console.log('Audio content written to file @ 6:53: ' + tempFile);
    return { filePath: "filePath653" }
})

Возможно ли, что эта функция была добавлена в fs?

Ответ 8

Для простой в использовании асинхронной конвертации всех обратных вызовов, чтобы обещать использовать некоторую библиотеку, такую ​​как "bluebird".

      .then(function(results) {
                fs.writeFile(ASIN + '.json', JSON.stringify(results), function(err) {
                    if (err) {
                        console.log(err);
                    } else {
                        console.log("JSON saved");
                        return results;
                    }
                })


            }).catch(function(err) {
                console.log(err);
            });

Попробуйте решение с обещанием (bluebird)

var amazon = require('amazon-product-api');
var fs = require('fs');
var Promise = require('bluebird');

var client = amazon.createClient({
    awsId: "XXX",
    awsSecret: "XXX",
    awsTag: "888"
});


var array = fs.readFileSync('./test.txt').toString().split('\n');
Promise.map(array, function (ASIN) {
    client.itemLookup({
        domain: 'webservices.amazon.de',
        responseGroup: 'Large',
        idType: 'ASIN',
        itemId: ASIN
    }).then(function(results) {
        fs.writeFile(ASIN + '.json', JSON.stringify(results), function(err) {
            if (err) {
                console.log(err);
            } else {
                console.log("JSON saved");
                return results;
            }
        })
    }).catch(function(err) {
        console.log(err);
    });
});