我的问题是解析大型xml文件(带有xml2js),以及循环(产品)中的forEach元素,下载图像并将其保存到文件中。 我写了这段代码:
var fs = require('fs');
var request = require('request');
var parseString = require('xml2js').parseString;
var baseUrl = 'http://shop.nag.ru/uploads/catalog_item_image_main/';
var async = require('async');
var processImg = require('./downloader');
var q = require('q');
var readFileSync = function (){
var xml = fs.readFileSync("./test.xml", "utf8");
return xml;
};
readFileSync.then(function(xml) {
parseString(xml, function (err, result) {
if(err)return error;
return result.product_list.product;
})
})
.then(function(products){
products.forEach(function(prdt) {
});
}).catch(function (err) {
console.log(err);
});
但是跑完后我得到了这个错误:
readFileSync.then(function(xml) {
^
TypeError: undefined is not a function
at Object.<anonymous> (D:\WorkVrp\nodeImageParser\processing.js:19:14)
at Module._compile (module.js:460:26)
at Object.Module._extensions..js (module.js:478:10)
at Module.load (module.js:355:32)
at Function.Module._load (module.js:310:12)
at Function.Module.runMain (module.js:501:10)
at startup (node.js:129:16)
at node.js:814:3
答案 0 :(得分:3)
我认为您将fs.readFileSync
误认为fs.readFileAsync
。前者是fs
的内置函数,它直接返回数据。后者是由 promisification by Bluebird创建的函数,它返回一个promise。
在这里,他们的使用方式有多么不同:
<强> fs.readFileSync 强>:
var fs = require('fs');
try {
var data = fs.readFileSync('./file.xml', 'utf8');
// do something with data
} catch(err) {
console.error(err);
}
<强> fs.readFileAsync 强>:
var fs = require('fs');
var Promise = require('bluebird');
Promise.promisifyAll(fs);
fs.readFileSyncAsync('./file.xml', 'utf8')
.then(function(data){
//do something with data
})
.catch(function(err){
console.error(err);
});
请注意实际创建require('bluebird')
所需的Promise.promisifyAll(fs)
和fs.readFileSyncAsync
,否则fs
无法使用readFile
随着希望被清除,以下是我认为您想要重新编写代码的方式:
我认为你需要的一些改变是:
您实际上并不需要fs.readFileAsync
功能,您可以直接使用parseString
。
require('xml2js')
来自xml2js
的{{1}}会更好fs
本身就像xml2js.parseStringAsync
并使用var fs = require('fs');
var request = require('request');
var xml2js = require('xml2js');
var Promise = require('bluebird');
Promise.promisifyAll(fs);
Promise.promisifyAll(request);
Promise.promisifyAll(xml2js);
var baseUrl = 'http://test.com/uploads/catalog_item_image_main/';
var processImg = require('./downloader');
var processImgAsync = Promise.promisify(processImg);
fs.readFileAsync("./test.xml", "utf8")
.then(xml2js.parseStringAsync)
.then(parseProductsAsync) // defined below
.then(processProductsAsync)
.then(function(){
console.log('All prdt have been processed successfully');
})
.catch(console.error);
function parseProductsAsync(xmljsonresult){
return xmljsonresult.product_list.product;
}
function processProductsAsync(products){
return Promise.all(products.map(function(product){
console.log('Processing file ' + product.sku);
var filename = product.sku + "";
filename = filename.replace(/\//g, '_');
return processImgAsync(baseUrl + filename + '_big.', filename);
}));
}
我也继续使用你previous question中的代码,这可能对你理解整个图片更有帮助:
{{1}}
答案 1 :(得分:0)
fs.readFileSync
返回结束值(字符串或缓冲区)。它是同步的。您的代码中没有任何承诺,因此您获得了TypeError
答案 2 :(得分:0)
readFileSync不返回承诺,使用它的方式是
value = readFileSync(filename,options);
值可以是字符串或缓冲区,具体取决于编码选项
请参阅https://nodejs.org/api/fs.html#fs_fs_readfilesync_filename_options