fs.writeFile在promise,异步同步的东西中

Mar*_*ich 43 synchronization amazon asynchronous node.js amazon-product-api

我的代码需要一些帮助.我是nodejs的新手,并且遇到很多麻烦.我想做什么:

  • 1)使用亚马逊产品(ASIN)获取.txt
  • 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);
        });
};
Run Code Online (Sandbox Code Playgroud)

小智 78

截至2018年......

...正确的答案是使用async/await与本机fs模块.升级到Node.js 10(主要云提供商已经支持)并执行此操作:

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');
Run Code Online (Sandbox Code Playgroud)

不要使用第三方软件包,也不要编写自己的包装器,这是不再需要的.

从Node开始11.14.0,你会收到一个警告,告知这个功能是实验性的,但它的工作正常,这是未来的发展方向.

  • 抬头这个标记为10.9.0的实验 (9认同)
  • 如果您使用“import”,您还可以使用“import fs from 'fs/promises';” (4认同)
  • 节点 11.x+ 中没有警告 (2认同)

Ant*_*onB 48

因为fs.writefile是一个传统的异步回调 - 你需要遵循promise规范并返回一个新的承诺,用一个解析和拒绝处理程序包装它,如下所示:

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

因此,在您的代码中,您可以在致电后立即使用它 .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);
  });
Run Code Online (Sandbox Code Playgroud)

  • 从 Node v8 开始,您可以使用 util.promisify() 将 fs I/O 函数转换为 promises,例如 `const util = require('util');` `const writeFile = util.promisify(fs.writeFile);` `...` `return writeFile(ASIN + '.json', JSON.stringify(results));` (4认同)

ama*_*ara 46

const util = require('util')
const fs_writeFile = util.promisify(fs.writeFile)
Run Code Online (Sandbox Code Playgroud)

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

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

  • 在node.js版本8中添加了`util.promisify`.认为此信息可能对想要使用它的人有所帮助. (11认同)

Kim*_*ern 11

如果您想将基于 Promise 的版本fs作为 ES 模块导入,您可以执行以下操作:

import { promises as fs } from 'fs'

await fs.writeFile(...)
Run Code Online (Sandbox Code Playgroud)

一旦节点 v14 发布(请参阅此PR),您还可以使用

import { writeFile } from 'fs/promises'
Run Code Online (Sandbox Code Playgroud)


Lew*_*wis 9

最后,最新的node.js版本v10.3.0本身支持fs promise.

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);
  });
Run Code Online (Sandbox Code Playgroud)

您可以查看官方文档以获取更多详细信息. https://nodejs.org/api/fs.html#fs_fs_promises_api

  • `const fs = require('fs').promises`,not/promises (2认同)

小智 5

对我有用的是 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');
  });
Run Code Online (Sandbox Code Playgroud)

例二。使用异步等待:

const fs = require("fs")

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

  console.log("done")
}

writeToFile()
Run Code Online (Sandbox Code Playgroud)


wra*_*ord 5

2023,节点 v16+,ESM,import使用 Promise

(我还对代码进行了一些重构以避免嵌套try..catch块,YMMV。

import * as fs from 'node:fs/promises';

async function doFile(filepath) { // choose a better name than `doFile` for your use case!!
    try {
        const fileData = await fs.readFile(filepath, {encoding: 'utf8'});
        var array = fileData.toString().split('\n');
        for (var i = 1; i < array.length; i++) {
            var ASIN = array[i];
            let results = await doClientStuff(args); // e.g. client.itemLookup
            await saveResults(ASIN, results);
        };
    } catch (error) {
        console.error(error?.message ?? error?.toString()); // or however you extract your error msg
    }
}
async function saveResults(ASIN, results) {
    try {
        await fs.writeFile(ASIN + '.json', JSON.stringify(results));
        console.log("JSON saved");
    } catch (error) {
        console.error(error?.message ?? error?.toString()); // or however you extract your error msg
    }
}
await doFile('./test.txt');
Run Code Online (Sandbox Code Playgroud)

这使用了OP希望我们fs默认导入的愿望。我个人会将其更改为仅导入您的个人函数并删除引用fs.以启用 esm tree-shaking:

import { readFile, writeFile } from 'node:fs/promises';

const fileData = await readFile(filepath, {encoding: 'utf8'}); // fs. removed

await writeFile(ASIN + '.json', JSON.stringify(results)); // fs. removed
Run Code Online (Sandbox Code Playgroud)

更多信息

如果未指定编码(使用 options.encoding),则数据将作为对象返回。否则,数据将是一个字符串。

请参阅节点文档以获取更多信息,包括同步/回调的替代用法。请务必在文档中为您的 Node 环境选择正确的版本。


trq*_*ong -2

为了易于使用异步转换所有回调以承诺使用一些库,如“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);
            });
Run Code Online (Sandbox Code Playgroud)

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

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);
    });
});
Run Code Online (Sandbox Code Playgroud)