node.js - trabajar - fs.writeFile en una promesa, asíncrono-síncrono cosas
trabajar con promesas javascript (7)
Necesito un poco de ayuda con mi código. Soy nuevo en nodejs y tengo muchos problemas con eso. Lo que estoy tratando de hacer:
- 1) obtener un .txt con los productos de Amazon (ASIN)
2) obtener todos los productos con el paquete amazon-product-api
3) guardar cada producto en un archivo .json
Mi código no funciona. Creo que me equivoqué con estas cosas asíncronas sincrónicas. ¡Ayúdame!
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);
});
};
A partir de 2018 ...
... la respuesta correcta es usar async / await con el módulo fs
nativo. Actualice a Node.js 10 (que ya es compatible con los principales proveedores de la nube) y haga esto:
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'');
No utilice paquetes de terceros y no escriba sus propios envoltorios, eso ya no es necesario.
A partir del Nodo 11.1.0
, recibirá una advertencia de que esta función es experimental, pero funciona bien y es el camino a seguir en el futuro.
Debido a que fs.writefile
es una devolución de llamada asíncrona tradicional, debe seguir la especificación de promesa y devolver una nueva promesa envolviéndola con un controlador de resolución y rechazo, como por ejemplo
return new Promise(function(resolve, reject) {
fs.writeFile("<filename.type>", data, ''<file-encoding>'', function(err) {
if (err) reject(err);
else resolve(data);
});
});
Así que en tu código lo .then()
así justo después de tu llamada a .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);
});
Finalmente, la última versión de node.js v10.3.0 ha soportado las promesas de forma nativa.
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);
});
Puedes consultar la documentación oficial para más detalles. https://nodejs.org/api/fs.html#fs_fs_promises_api
Para que sea fácil de usar, convierta de forma asíncrona todas las devoluciones de llamada a la promesa de usar alguna biblioteca como "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);
});
Probar la solución con promesa (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);
});
});
decir
const util = require(''util'')
const fs_writeFile = util.promisify(fs.writeFile)
https://nodejs.org/api/util.html#util_util_promisify_original
Esto es menos propenso a los errores que la respuesta más votada.
Actualización de septiembre de 2017 : fs-promise
ha sido desaprobada en favor de fs-extra
.
No lo he usado, pero podrías mirar fs-promise . Es un módulo de nodo que:
Proxies todos los métodos fs asíncronos exponiéndolos como promesas / promesas compatibles con A + (cuándo, Q, etc.). Pasa todos los métodos de sincronización a través de como valores.
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)
});