node.js fs.writeFile 在承诺中,异步同步的东西

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31978347/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 19:14:41  来源:igfitidea点击:

fs.writeFile in a promise, asynchronous-synchronous stuff

node.jsasynchronoussynchronizationamazonamazon-product-api

提问by Markus Schmidlich

I need some help with my code. I'm new at Node.js and have a lot of trouble with it.

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

What I'm trying to do:

我正在尝试做的事情:

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

1) 使用亚马逊产品 (ASIN) 获取 .txt ;

2) Fetch all products using the amazon-product-apipackage;

2) 使用amazon-product-api包获取所有产品;

3) Save each product in a .json file.

3) 将每个产品保存在 .json 文件中。

My code is not working. I think I messed up with this asynchronous-synchronous stuff - help me!

我的代码不起作用。我想我搞砸了这个异步同步的东西 - 帮帮我!

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

回答by

As of 2019...

截至2019年...

...the correct answer is to use async/await with the native fspromises moduleincluded in node. Upgrade to Node.js 10 or 11 (already supported by major cloud providers) and do this:

...正确的答案是将 async/await 与包含在 node 中的本机fspromises 模块一起使用。升级到 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');

Do not use third-party packages and do not write your own wrappers, that's not necessary anymore.

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

No longer experimental

不再是实验性的

Before Node 11.14.0, you would still get a warning that this feature is experimental, but it works just fine and it's the way to go in the future. Since 11.14.0, the feature is no longer experimental and is production-ready.

在 Node 之前11.14.0,您仍然会收到警告,指出此功能是实验性的,但它运行良好,并且是未来的发展方向。由于11.14.0,该功能不再是实验性的,并且可以投入生产。

What if I prefer importinstead of require?

如果我更喜欢import而不是require怎么办?

It works, too - but only in Node.js versions where this feature is not marked as experimental.

它也可以工作 - 但仅在此功能未标记为实验性的 Node.js 版本中。

import { promises as fs } from 'fs';

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

回答by AntonB

Because fs.writefileis a traditional asynchronous callback - you need to follow the promise spec and return a new promise wrapping it with a resolve and rejection handler like so:

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

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

So in your code you would use it like so right after your call to .then():

因此,在您的代码中,您可以在调用以下代码后立即使用它.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);
  });

回答by amara

say

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

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

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

this is less prone to bugs than the top-voted answer

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

回答by Lewis

Finally, the latest node.js release v10.3.0 has natively supported fs promises.

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

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

回答by rouan

UpdateSept 2017: fs-promisehas been deprecated in favour of fs-extra.

2017 年 9 月更新fs-promise已弃用fs-extra.



I haven't used it, but you could look into fs-promise. It's a node module that:

我没用过,但你可以看看fs-promise。这是一个节点模块,它:

Proxies all async fs methods exposing them as Promises/A+ compatible promises (when, Q, etc). Passes all sync methods through as values.

代理所有异步 fs 方法,将它们公开为 Promises/A+ 兼容的承诺(when、Q 等)。将所有同步方法作为值传递。

回答by Kim Kern

If you want to import the promise based version of fsas an ES module you can do:

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

import { promises as fs } from 'fs'

await fs.writeFile(...)


As soon as node v14 is released (see this PR), you can also use

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

import { writeFile } from 'fs/promises'

回答by Saeed Zarinfam

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

回答by Rahul Sadaphal

Use fs.writeFileSync inside the try/catch block as below.

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

回答by trquoccuong

For easy to use asynchronous convert all callback to promise use some library like "bluebird" .

为了易于使用异步将所有回调转换为承诺,请使用诸如“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);
            });

Try solution with promise (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);
    });
});