I'm having issues with reading the data from a file created with fs.createWriteStream.
It looks like the stream.write get executed at the end of the program after the file is read as opposed to when they are called (which would explain why there is nothing in variable_3 at the time of outputting it).
The function used is as follow (simplified):
module.exports = async data1 => {
console.log('start');
try {
const stream = fs.createWriteStream(filename_1, { flags: "a" });
console.log('stream created');
stream.write("some data", (err) => {
if (err) {
console.log(err.message);
} else {
console.log("data written");
}
});
for (const variable_1 of object_1) {
const variable_2 = await function2({
// generates a buffer
});
stream.write(variable_2, (err) => {
if (err) {
console.log(err.message);
} else {
console.log("data written");
}
});
}
stream.end();
console.log('stream ended');
console.log('opening file');
const variable_3 = fs.readFileSync(filename_1);
console.log('file opened and read with data: ' + variable_3);
return;
} catch (error) {
console.log(error);
}
};
Output:
> start
> stream created
> stream ended
> opening file
> file opened and read with data:
> data written
> data written
Once the code has run however, when I open filename_1 (via the explorer), the whole data is present?!
Got it sorted in the end.
Didn't realise the stream functions don't return a promise so I had to manually return a promise.
Here is the code changed:
module.exports = async data1 => {
console.log('start');
try {
const stream = fs.createWriteStream(filename_1, { flags: "a" });
console.log('stream created');
stream.write("some data", (err) => {
if (err) {
console.log(err.message);
} else {
console.log("data written");
}
});
for (const variable_1 of object_1) {
const variable_2 = await function2({
// generates a buffer
});
stream.write(variable_2, (err) => {
if (err) {
console.log(err.message);
} else {
console.log("data written");
}
});
}
stream.end();
console.log('stream ended');
console.log('opening file');
const variable_3 = fs.readFileSync(filename_1);
console.log('file opened and read with data: ' + variable_3);
return new Promise(resolve => {
stream.on('finish', () => {
resolve('done');
console.log("createNRRD is done");
});
});
} catch (error) {
console.log(error);
}
};
Related
function Getir() {
var options =
{
host: 'example',
port: 443,
path: '/myUrl'
};
get(options, function (http_res) {
var data = "";
http_res.on("data", function (chunk) {
data += chunk;
});
http_res.on("end", function () {
writeFile('NewHtml.txt', `${data}`, 'utf8', (err) => {
if (err) console.log(err);
});
});
});
}
function DegistirDuzenle() {
if (existsSync("./DatabaseHtml.txt")) {
var DataBaseHtml = readFileSync("./DatabaseHtml.txt", 'utf-8', (err) => { if (err) console.log(err) });
var MyHtml = readFileSync("./NewHtml.txt", 'utf-8', (err) => {if (err) console.log(err) });
if (MyHtml == DataBaseHtml) {
unlink("./NewHtml.txt", (err)=>{ if(err) console.log(err)});
console.log("değişiklik yapılmadı");
} else {
//notification
console.log("değişiklik yapıldı");
//Change
unlink('./DatabaseHtml.txt', (err) => { if(err) console.log(err); });
writeFile('./DatabaseHtml.txt', `${MyHtml}`, 'utf-8', (err) => { if(err) console.log(err); });
unlink('./NewHtml.txt', (err) => { if(err) console.log(err); });
}
}
else {
writeFile('DatabaseHtml.txt', `NewDataBaseHtml`, 'utf8', (err) => {
if (err) console.log(err);
});
}
}
async function Mysystem() {
let mypromis = new Promise((resolve, reject)=>{
resolve(Getir());
});
await mypromis.then(DegistirDuzenle());
}
Mysystem();
I want to create a txt file, read it and delete it later. I have 2 function 1.(Getir()) Create txt, 2.(DegistirDuzenle()) read txt and delete but 2. function starts working first and I getting error. "Error: ENOENT: no such file or directory, open './NewHtml.txt'"
async function Mysystem() {
let mypromis = new Promise((resolve, reject)=>{
resolve(Getir());
});
await mypromis()
await DegistirDuzenle()
}
Mysystem()
You should use
async function Mysystem() {
await Getir();
await DegistirDuzenle();
}
or
function Mysystem() {
return Getir().then(DegistirDuzenle);
}
but not a mix of them. Also notice that when passing the DegistirDuzenle function to .then() as a callback, it shouldn't be invoked (passing the result of a call, not passing the function). Alternatively, you could write .then((getirResult) => DegistirDuzenle()).
Also, for this to work, you'll need to properly promisify the code in Getir and DegistirDuzenle.
This code works fine to upload image to cloudinary.
Let's say the image is uploaded but then there is a mongodb error.
Then I want to delete the image that is already at cloudinary but how can i get the value of "cloudinary_id" in my catch block?
createGalery: async (req, res) => {
try {
const result = await cloudinary.uploader.upload(req.file.path, {
folder: 'Test'
});
let image = result.secure_url;
let cloudinary_id = result.public_id;
const newGalery = new Galery({
image,
cloudinary_id,
});
await newGalery.save();
res.json({ msg: 'successful' });
} catch (err) {
try {
console.log(cloudinary_id);
// How to delete when mongodb save fails?
//await cloudinary.uploader.destroy(result.public_id);
} catch {
return res.status(500).json({ msg: err.message });
}
return res.status(500).json({ msg: err.message });
}
}
Nest your try blocks:
createGalery: async (req, res) => {
try {
const result = await cloudinary.uploader.upload(req.file.path, {
folder: 'Test'
});
const cloudinary_id = result.public_id;
try {
const newGalery = new Galery({
image: result.secure_url,
cloudinary_id,
});
await newGalery.save();
} catch (mongoErr) {
console.log(`Removing ${cloudinary_id} due to failed save`);
await cloudinary.uploader.destroy(cloudinary_id);
throw mongoErr;
}
res.json({ msg: 'successful' });
} catch (err) {
return res.status(500).json({ msg: err.message });
}
}
Move the declaration of your cloudinary_id variable outside of the try/catch block:
let cloudinary_id;
try {
// ...
cloudinary_id = result.public_id; // without the "let" keyword in front of it
// ...
} catch (err) {
console.log(cloudinary_id);
if (cloudinary_id) {
await deleteFromCloudinary(cloudinary_id);
// if cloudinary_id is not set, the error was thrown
// before setting it (i.e. while uploading to cloudinary)
}
}
I have two models: ModelA and ModelB, I am trying to copy a tags = Array() column from ModelB into ModelA, like this:
function run() {
ModelA.find({}).limit(500).cursor()
.on('data', function(doc) {
let refID = doc.ref_id;
ModelB.findOne({_id: refID}).exec(function(err, modelb) {
if (err) {
console.log(`[Error]: Getting modelb ${refID}`);
}
if (modelb) {
if (modelb.tags.length > 0) {
doc.tags = modelb.tags;
}
}
});
doc.processed = true;
doc.save(function(err, hackAlert) {
if (err) {
console.log('[Error]: Saving ModelA: ' + err);
}
console.log(`Saved: ${doc._id}`);
});
})
.on('error', function(err){
console.log('[Error]');
})
.on('end', function(){
console.log('Done');
});
}
The script obviously saves all ModelA instances with processed = true but given the asynchronous nature of Node, ModelA documents end up without tags.
I'm new to this if you can't tell. I wanted to know what is the best, modern way to "await" for the ModelB.findOne() query to finish before saving ModelA ?
You can simply move the code to be called on the callback of your first query:
function run() {
ModelA.find({}).limit(500).cursor()
.on('data', function(doc) {
let refID = doc.ref_id;
ModelB.findOne({_id: refID}).exec(function(err, modelb) {
if (err) {
console.log(`[Error]: Getting modelb ${refID}`);
}
if (modelb) {
if (modelb.tags.length > 0) {
doc.tags = modelb.tags;
}
}
doc.processed = true;
doc.save(function(err, hackAlert) {
if (err) {
console.log('[Error]: Saving ModelA: ' + err);
}
console.log(`Saved: ${doc._id}`);
});
});
})
.on('error', function(err){
console.log('[Error]');
})
.on('end', function(){
console.log('Done');
});
}
For a more up-to-date approach using async/await and Promises:
async function run () {
ModelA.find({}).limit(500).cursor()
.on('data', async function (doc) {
let refID = doc.ref_id;
const modelb = await ModelB.findOne({_id: refID}).exec()
.catch(() => console.log(`[Error]: Getting modelb ${refID}`));
if (modelb) {
if (modelb.tags.length > 0) {
doc.tags = modelb.tags;
}
}
doc.processed = true;
await doc.save().exec()
.catch(err => console.log('[Error]: Saving ModelA: ' + err))
console.log(`Saved: ${doc._id}`);
})
.on('error', function (err){
console.log('[Error]');
})
.on('end', function () {
console.log('Done');
});
}
I've the following code which works
if (fs.existsSync(dirName)) {
__writeFile();
return;
}
function __writeFile() {
writeIntoFile(readStream, destFileName, reject);
numOfFiles++;
}
But after execute it im getting warning:
(node:3547) [DEP0013] DeprecationWarning: Calling an asynchronous
function without callback is deprecated.
Any idea how to avoid this ?
update this is all the code
yauzl.open(filePath, (err, zipFile) => {
if (err) {
__rejectAndLog(err);
return;
}
zipFile.on('entry', __processEntry.bind(null, zipFile))
.once('error', __rejectAndLog)
.once('close', () => {
resolve();
});
});
function __processEntry(zipFile, entry) {
if (/\/$/.test(entry.fileName)) {
return;
}
zipFile.openReadStream(entry, (err, readStream) => {
if (err) {
__rejectAndLog(err);
return;
}
//Path to drop the files
let destFileName = '/' + entry.fileName;
let dirName = path.join(res);
if (fs.existsSync(dirName)) {
__writeFile();
return;
}
mkdirp(dirName, (err) => {
if (err) {
__rejectAndLog(err);
} else {
__writeFile();
}
});
function __writeFile() {
writeIntoFile(readStream, destFileName, reject);
numOfFiles++;
}
});
}
as requested this is the content of write into file
function writeIntoFile(readStream, filePath, onError) {
if (fs.existsSync(filePath)) {
fs.chmod(filePath, '777');
}
var ws = fs.createWriteStream(filePath);
ws.on('error', function (error) {
onError(error);
});
readStream.pipe(ws);
};
update2
I try to change it according the answer below and its not working (and where should I put the mode 777)
function writeIntoFile(readStream, filePath, onError) {
if (fs.existsSync(filePath)) {
fs.chmod(filePath, 0o777, function (err) {
var ws = fs.createWriteStream(filePath);
ws.on('error', function (error) {
onError(error);
});
readStream.pipe(ws);
});
}
};
i want to run a script that will create a directory and within a file and subdirectory, something like this
main-folder
> sub-folder
> file
so far i haven't had any luck, my thought is trying to writeFile within the mkDir function
const fileGenerator = (fileName, fileContent) => {
fs.writeFile(fileName, fileContent, (err) => {
if (err) throw err;
console.log('The file has been saved!');
});
}
fs.mkdir('main-folder', err => {
if (err) {
console.log(err);
} else {
fileGenerator('index.html', 'hello');
console.log('Directory Created');
fs.mkdir('sub-folder', err => {
if (err) {
console.log(err);
} else {
console.log('Directory Created');
}
})
}
})
The code is 'working as inteded'. The place where're you creating your subfolder and file is just the callback. The mkdir function from the Node Filesystem still needs the full path. It doesn't know that its under "main-folder".
See the edited code:
const fs = require('fs');
const fileGenerator = (fileName, fileContent) => {
fs.writeFile(fileName, fileContent, (err) => {
if (err) throw err;
console.log('The file has been saved!');
});
}
fs.mkdir('main-folder', err => {
if (err) {
console.log(err);
} else {
fileGenerator('main-folder/index.html', 'hello');
console.log('Directory Created');
fs.mkdir('main-folder/sub-folder', err => {
if (err) {
console.log(err);
} else {
console.log('Directory Created');
}
})
}
})
Your code created the main-folder, sub-folder and index.html, just all relative to js file.