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

时间:2015-08-13 02:04:40

标签: node.js asynchronous synchronization amazon amazon-product-api

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

我正在尝试做什么:

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

10 个答案:

答案 0 :(得分:43)

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

答案 1 :(得分:40)

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

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

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

答案 2 :(得分:35)

截至2019年...

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

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

不再实验

在节点11.14.0之前,您仍然会收到警告,告知您此功能是实验性的,但效果很好,是将来的方法。自11.14.0起,该功能不再是实验性的,并且已经可以量产。

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

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

import { promises as fs } from 'fs';

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

答案 3 :(得分: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 :(得分:7)

如果要将基于{promise的版本的fs导入为ES模块,则可以执行以下操作:

import { promises as fs } from 'fs'

await fs.writeFile(...)

释放节点v14后(请参阅此PR),您也可以使用

import { writeFile } from 'fs/promises'

答案 5 :(得分:4)

更新 2017年9月fs-promise已被弃用,转而使用fs-extra

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

  

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

答案 6 :(得分: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)
    });

答案 7 :(得分:2)

对我有用的是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()

答案 8 :(得分:-1)

为了易于使用异步转换所有回调承诺使用一些像“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);
            });

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

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

答案 9 :(得分:-1)

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