一个异步同步的承诺中的 fs.writeFile

我需要一些代码方面的帮助。我是 Node.js 的新手,在这方面遇到了很多麻烦。

What I'm trying to do:

  1. Fetch a .txt with Amazon products (ASINs) ;

  2. 使用 亚马逊产品 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];


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);
});
};
162073 次浏览

为了便于使用异步转换所有回调承诺使用一些库,如“蓝鸟”。

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

用承诺尝试解决方案(蓝鸟)

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

更新 2017年9月: fs-promise已被弃用,取而代之的是 fs-extra


我还没有使用它,但是你可以查看 我保证,它是一个节点模块:

代理所有将它们公开为承诺/A + 兼容的异步 fs 方法 promises (when, Q, etc). Passes all sync methods through as values.

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

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

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

这比投票最多的答案更不容易出错

最后,最新的 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);
});

You can check the official documentation for more details. https://nodejs.org/api/fs.html#fs_fs_promises_api

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

到2019年。

... 正确的答案是使用 本机 fs承诺模块 包含在节点中的异步/等待。升级到 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');

不要使用第三方软件包,也不要编写自己的包装器,这已经没有必要了。

不再是实验性的了

在 Node 11.14.0之前,您仍然会得到一个警告,说这个特性是实验性的,但是它工作得很好,这是未来的发展方向。自 11.14.0以来,该特性不再是实验性的,而是可以投入生产的。

如果我更喜欢 import而不是 require呢?

它也可以工作,但是只能在 Node.js 版本中使用,这个特性并没有被标记为实验性的。

import { promises as fs } from 'fs';


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

在 try/catch 块中使用 fs.writeFileSync,如下所示。

var fs = require('fs');
try {
const file = fs.writeFileSync(ASIN + '.json', JSON.stringify(results))
console.log("JSON saved");
return results;
} catch (error) {
console.log(err);
}

如果你想导入基于承诺的 fs版本作为 ES 模块,你可以这样做:

import { promises as fs } from 'fs'


await fs.writeFile(...)

一旦发布了节点 v14(参见此 公关) ,您还可以使用

import { writeFile } from 'fs/promises'

对我有用的是家庭服务承诺。

例一:

const fs = require("fs")


fs.promises
.writeFile(__dirname + '/test.json', "data", { encoding: 'utf8' })
.then(() => {
// Do whatever you want to do.
console.log('Done');
});

示例二: 使用异步-等待:

const fs = require("fs")


async function writeToFile() {
await fs.promises.writeFile(__dirname + '/test-22.json', "data", {
encoding: 'utf8'
});


console.log("done")
}


writeToFile()

使用 require('fs/promises')

var fs = require('fs/promises'); // Since 11.14.0
var path = require('path'); // to help us to join better the paths


var content = JSON.stringify(["this is your content"]); // Must be a string to be written.


fs
.writeFile(path.join(__dirname, 'test.json'), content, { encoding: 'utf8' })
.then(() => {
console.log('Write is done!');
});

示例使用异步/等待

var fs = require('fs/promises'); // Since 11.14.0
var path = require('path'); // to help us to join better the paths


var content = JSON.stringify(["this is your content"]); // Must be a string to be written.


(async function autorun(){
  

await fs.writeFile(path.join(__dirname, 'test.json'), content, { encoding: 'utf8' })
console.log('Write is done!');


})() // This is called a IIFE: Immediately invoked function expression