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

问题描述 投票:32回答:7

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

我正在尝试做什么:

1)使用Amazon产品(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);
        });
};
node.js asynchronous amazon sync amazon-product-api
7个回答
51
投票

As of 2019...

...正确的答案是使用async / await与节点中包含的the native fs promises module。升级到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');

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

No longer experimental

在节点11.14.0之前,你仍会得到一个警告,这个功能是实验性的,但是它运行得很好,这是未来的发展方向。自11.14.0以来,该功能不再具有实验性,并且可以投入生产。

What if I prefer import instead of require?

它也有效 - 但仅限于此功能未标记为实验的Node.js版本。

import { promises as fs } from 'fs';

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

46
投票

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

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

41
投票

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

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

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


8
投票

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

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


4
投票

2017年9月更新:fs-promise已被弃用,以支持fs-extra


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

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


2
投票
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)
    });

-1
投票

为了易于使用异步转换所有回调承诺使用一些像“蓝鸟”的库。

      .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);
    });
});
© www.soinside.com 2019 - 2024. All rights reserved.