Reputation: 2904
MY issue is parse large xml file (with xml2js), and forEach element in cycle(product) , download image and save it to file. I wrote this code:
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);
});
But after run I got this error :
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
Upvotes: 1
Views: 1910
Reputation: 34627
I think you're mistaking fs.readFileSync
for fs.readFileAsync
. The former is an in-built function of fs
which returns the data directly. The latter is a function created by promisification by Bluebird which returns a promise.
Here's how differently they'd be used:
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);
});
Notice the require('bluebird')
and Promise.promisifyAll(fs)
which are required to actually create fs.readFileSyncAsync
which otherwise wouldn't have been available on fs
With that hopefully cleared, here's how I think you'd want to re-write your code:
Some changes I think you need are:
You don't actually need the function readFile
, you can just use fs.readFileAsync
directly.
Your parseString
which comes from require('xml2js')
would be better if you just promisified xml2js
itself like fs
and used xml2js.parseStringAsync
I've also gone ahead and taken the code from your previous question which presumably be more helpful in you understanding the whole picture:
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);
}));
}
Upvotes: 3
Reputation: 1
readFileSync does not return a promise, the way to use it is
value = readFileSync(filename, options);
value will be either a string or buffer, depending on encoding option
see https://nodejs.org/api/fs.html#fs_fs_readfilesync_filename_options
Upvotes: 0
Reputation: 46323
fs.readFileSync
returns an end value (either string or a buffer). It SYNCHRONOUS. There is no promise involved in your code, and so you get the TypeError
Upvotes: 0