Replacing util.pump() in Node.js - javascript

I recently updated to the latest version of Node.js (1.10~) from 0.8~, and I've been getting a message when running that says:
util.pump() is deprecated. Use readableStream.pipe() instead.
I've tried to switch my functions to say readableStream.pipe(), but I don't think it's working the same.
So I have three questions:
Why is util.pump deprecated?
How do I switch to readableStream.pipe()?
OR 3. How do I turn off this warning?
Here is the code where I'm using it (with mustache)
var stream = mu.compileAndRender(template_file, json_object_from_db);
util.pump(stream, res);
When I replace util.pump with readableStream.pipe, I get this error:
ReferenceError: readableStream is not defined
Can anyone help point me in the right direction?

Okay, so this question was a pretty easy answer after some more experimentation (though documentation was null).
Basically, readableStream is just a variable you're supposed to replace with your stream. So in my case, the answer is:
stream.pipe(res);
You just replace util, basically, with the stream. Easy peezy.

I Think the following link will help for your work ! https://groups.google.com/forum/#!msg/nodejs/YWQ1sRoXOdI/3vDqoTazbQQJ
var readS = fs.createReadStream("fileA.txt");
var writeS = fs.createWriteStream("fileB.txt");
util.pump(readS, writeS, function(error)
// Operation done
});
=====>
var readS = fs.createReadStream("fileA.txt");
var writeS = fs.createWriteStream("fileB.txt");
readS.pipe(writeS);
readS.on("end", function() {
// Operation done
});

You can look this link http://nodejs.cn/api/stream.html
This is emitted whenever the stream.pipe() method is called on a readable stream, adding this writable to its set of destinations.
var writer = getWritableStreamSomehow();
var reader = getReadableStreamSomehow();
writer.on('pipe', (src) => {
console.error('something is piping into the writer');
assert.equal(src, reader);
});
reader.pipe(writer);

Related

Alternative to eval() in node script

I am working on a script that runs during our build process in Jenkins right before npm install. My issue is that I need to download a JavaScript file from an external resource and read a variable from it.
unzipper.on('extract', () => {
const content = fs.readFileSync(`${outputDir}/js/en.js`, 'utf8');
eval(content); // Less smellier alternative?
if (obj) {
const str = JSON.stringify(obj);
fs.writeFileSync(`${outputDir}/public/data.json`, str);
} else {
throw 'Variable `obj` not found';
}
});
I know that "eval is evil", but any suggested alternatives I've found online don't seem to work.
I have tried different variations of new Function(obj)(), but Node seems to exit the script after (the if-case never runs).
Ideas?
Since node.js provides the API to talk to the V8 runner directly, it might be a good idea to use it. Basically, it's the API used by node's require under the hood.
Assuming the js file in question contains the variable obj we're interested in, we do the following:
read the code from the file
append ; obj to the code to make sure it's the last expression it evaluates
pass the code to V8 for evaluation
grab the return value (which is our obj):
const fs = require('fs'),
vm = require('vm');
const code = fs.readFileSync('path-to-js-file', 'utf8');
const obj = vm.runInNewContext(code + ';obj');
This answer is heavily based on #georg's comments, but since it helped me I'll provide it as an alternative answer.
Explanation in the comments.
let content = fs.readFileSync(`${outputDir}/js/en.js`, 'utf8');
content += '; module.exports=obj'; // Export "obj" variable
fs.writeFileSync(`${outputDir}/temp`, content); // Create a temporary file
const obj = require(`${outputDir}/temp`); // Import the variable from the temporary file
fs.unlinkSync(`${outputDir}/temp`); // Remove the temporary file

Node.js console.log() in txt file

I have another question (last question). At the moment i am working on a Node.js project and in this I have many console.log() functions. This has worked okay so far but I also want everything that's written to the console to also be written in a log-file. Can someone please help me?
For example:
Console.log('The value of array position [5] is '+ array[5]);
In my real code its a bit more but this should give you an idea.
Thank you hopefully.
Just run the script in your terminal like this...
node script-file.js > log-file.txt
This tells the shell to write the standard output of the command node script-file.js to your log file instead of the default, which is printing it to the console.
This is called redirection and its very powerful. Say you wanted to write all errors to a separate file...
node script-file.js >log-file.txt 2>error-file.txt
Now all console.log are written to log-file.txt and all console.error are written to error-file.txt
I would use a library instead of re-inventing the wheel. I looked for a log4j-type library on npm, and it came up with https://github.com/nomiddlename/log4js-node
if you want to log to the console and to a file:
var log4js = require('log4js');
log4js.configure({
appenders: [
{ type: 'console' },
{ type: 'file', filename: 'logs/cheese.log', category: 'cheese' }
]
});
now your code can create a new logger with
var logger = log4js.getLogger('cheese');
and use the logger in your code
logger.warn('Cheese is quite smelly.');
logger.info('Cheese is Gouda.');
logger.debug('Cheese is not a food.');
const fs = require('fs');
const myConsole = new console.Console(fs.createWriteStream('./output.txt'));
myConsole.log('hello world');
This will create an output file with all the output which can been triggered through console.log('hello world') inside the console.
This is the easiest way to convert the console.log() output into a text file.`
You could try overriding the built in console.log to do something different.
var originalLog = console.log;
console.log = function(str){
originalLog(str);
// Your extra code
}
However, this places the originalLog into the main scope, so you should try wrapping it in a function. This is called a closure, and you can read more about them here.
(function(){
var originalLog = console.log;
console.log = function(str){
originalLog(str);
// Your extra code
})();
To write files, see this stackoverflow question, and to override console.log even better than the way I showed, see this. Combining these two answers will get you the best possible solution.
Just write your own log function:
function log(message) {
console.log(message);
fs.writeFileSync(...);
}
Then replace all your existing calls to console.log() with log().
#activedecay's answer seems the way to go. However, as of april 30th 2018, I have had trouble with that specific model (node crashed due to the structure of the object passed on to .configure, which seems not to work in the latest version). In spite of that, I've managed to work around an updated solution thanks to nodejs debugging messages...
const myLoggers = require('log4js');
myLoggers.configure({
appenders: { mylogger: { type:"file", filename: "path_to_file/filename" } },
categories: { default: { appenders:["mylogger"], level:"ALL" } }
});
const logger = myLoggers.getLogger("default");
Now if you want to log to said file, you can do it just like activedecay showed you:
logger.warn('Cheese is quite smelly.');
logger.info('Cheese is Gouda.');
logger.debug('Cheese is not a food.');
This however, will not log anything to the console, and since I haven't figured out how to implement multiple appenders in one logger, you can still implement the good old console.log();
PD: I know that this is a somewhat old thread, and that OP's particular problem was already solved, but since I came here for the same purpose, I may as well leave my experience so as to help anyone visiting this thread in the future
Here is simple solution for file logging
#grdon/logger
const logger = require('#grdon/logger')({
defaultLogDirectory : __dirname + "/logs",
})
// ...
logger(someParams, 'logfile.txt')
logger(anotherParams, 'anotherLogFile.log')

ESLINT: no-unused-vars, stream conditional pipe use case

So i have the following function:
function buildJavaScript(file) {
var manifestRoot,
stream;
validateManifestSection(file.manifest, 'javascript');
if (file.manifest.javascript.disabled) {
return;
}
manifestRoot = path.dirname(file.path);
stream = gulp.src(path.join(manifestRoot, file.manifest.javascript.src))
.pipe(gulpBrowserify())
.pipe(gulpRename(file.manifest.javascript.dest));
if (file.manifest.javascript.minify) {
stream = stream.pipe(gulpUglify());
}
stream = stream.pipe(gulp.dest(manifestRoot));
}
Its purpose is part of a gulp task, receives an object representing a manifest file then browserifies and conditionally uglifies it.
Now when i ESLint it i get the following error:
error no-unused-vars : 'stream' is defined but never used.
NOTE: i don't make common practice of linting my build files, this was part of testing the linter and its behavior here caught my attention.
I get that you need more than just assignment for it to be satisfied which is a good thing otherwise it could be easily fooled.
However in the instance above where the variable is a stream and assignment and chaining is enough to warrant use how do you get ESLint to be happy?
Or am i doing it wrong and that is not how your meant to conditionally pipe a stream?
I get if i was to return stream or pass it into another method it would please the linter but that doesn't seem right, i don't need to return it for use elsewhere.
Thanks for any help or insights.
EDIT:
In trying to pinpoint the issue ive reduced the method down to the following which still has the issue:
function buildJavaScript(file) {
var stream;
stream = gulp
.src(path.join('', file.manifest.javascript.src))
.pipe(gulpBrowserify())
.pipe(gulpRename(file.manifest.javascript.dest));
if (file.manifest.javascript.minify) {
stream = stream.pipe(gulpUglify());
}
}
I can understand its reasoning, technically all I am doing is assignment, not consumption elsewhere but its the context of the assignment which means the variable is being used.

overwrite backbone History start method

Based on a working web application with (Backbone.js 1.0.0), I need to overwrite history start method, to force polling to detect hash changes, and discard other options. On a new file I do this:
var myHistory = Backbone.History.extend({
start: function (options) {
if (History.started) throw new Error("Backbone.history has already been started");
History.started = true;
// code here
}
});
Backbone.history = new myHistory;
As result, I get an Error: ReferenceError: Undefined variable: History.
any hints? Thanks!
I know this question is fairly old, and you've probably solved it by now, but I recently had to do a similar thing. For me I replaced where it said 'History.started' with 'Backbone.History.started', as History.started is a variable in the original Backbone library.

Windows 8 IndexedDB createObjectStore

Trying to build a Metro app using Javascript and having issues with IndexedDb. I cannot create an object store. My code is shown below. I'm doing this on success of the open() function.
dbReq.onsuccess = function (evt) {
var txn = evt.target.transaction;
var db = evt.target.result;
if (!db.objectStoreNames.contains("test")) {
var store = db.createObjectStore("test");
}
}
Every time, it throws an exception on the 'createObjectStore' call that says
0x800a139e - JavaScript runtime error: [object IDBDatabaseException]
Over here they talk about it and it's a nice example to look at too, but still, did not help me.
Notice that control hits the one line of code inside 'if' statement. So 'db' is not null and is valid. But I saw that the transaction is null - not sure if that is an issue or even if you are supposed to get a valid transaction back at this point.
Not sure why it was not working. Switched to using roaming settings and it is very easy to use.
roamingSettings.values[SETTING_NAME] = SETTING_VALUE;
To read, of course,
var temp = roamingSettings.values[SETTING_NAME];

Categories