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);
});
});