We have a gulpfile with ~12 tasks, 4 of which are activated by a gulp.watch. I would like to use gulp-notify when a task started by gulp.watch completes. I don't want gulp-notify to do anything if a task is run directly. Sample code below:
const
debug = require("gulp-debug"),
gulp = require("gulp"),
notify = require("gulp-notify");
gulp.task("scripts:app", function () {
return gulp.src(...)
.pipe(debug({ title: "tsc" }))
.pipe(...); // <--- if i add notify here,
// I will always get a notification
});
gulp.task("watch", function () {
gulp.watch("ts/**/*.ts", ["scripts:app"]);
});
If I pipe to notify inside the 'scripts:app' task, it will make a notification every time that task runs, regardless of how that task was started. Again, I want to notify when the watched task completes.
I considered adding a task 'scripts:app:notify' that depends on 'scripts:app', but if possible I'd like to avoid creating "unnecessary" tasks.
I also tried the following:
gulp.watch("ts/**/*.ts", ["scripts:app"])
.on("change", function (x) { notify('changed!').write(''); });
But that results in a notification for every file changed. I want a notification when the task completes.
In other words, if I run gulp scripts:app, I should not get a notification. When I run gulp watch and change a watched file, I should get a notification.
How can I do this?
Try adding params to your build script:
function buildApp(notify){
return gulp.src(...)
.pipe(...)
.pipe(function(){
if (notify) {
//drop notification
}
});
});
}
//Register watcher
gulp.watch("ts/**/*.ts", function(){
var notify = true;
buildApp(notify);
});
//Register task so we can still call it manually
gulp.task("scripts:app", buildApp.bind(null, false));
As you can see, buildApp is a simple function. It's callable through a watcher or a "normal" task registration.
Related
say I have a long task that starts running when a person connects to InitializeDB. (Of course with authorization in the future, but left that out for now).
'post /initializeDB':'OrderController.initializeAll',
Now the problem is: the initialize function should never be run twice. - I know ideally I set up a taskmanager which just starts a task in the background which I could poll.
However for current simplicity, (and to show a proof of concept) is it possible for a sails route to "know" that another connection/route is already running? So that if I connect twice to /initializeDB it won't try to initialize the database twice?
You can use a variable in your controller - just toggle it to true when the process is running, something like that. So, in OrderController.js:
var initializeRunning = false;
module.exports = {
initializeAll: function(req, res) {
// return benign result if already running
if (initializeRunning) {
return res.send({alreadyRunning: true});
}
// start running
initializeRunning = true;
// using setTimeout as a stand-in for a long async process
setTimeout(function() {
// finished the process
res.send({complete: true});
// if you want to allow this method to run again later, unset your toggle
initializeRunning = false;
}, 3000);
},
};
I have a Node.js game server and I start it by running nodemon app.js. Now, every time I edit a file the server restarts. I have implemented save and load functions and I want every time the game server restarts (due to the file chages) the game to be saved before restarting so that I can load the previous state after the restart.
Something like this is what I want:
process.on('restart', function(doneCallback) {
saveGame(doneCallback);
// The save game is async because it is writing toa file
}
I have tried using the SIGUR2 event but it was never triggered. This is what I tried, but the function was never called.
// Save game before restarting
process.once('SIGUSR2', function () {
console.log('SIGUR2');
game.saveGame(function() {
process.kill(process.pid, 'SIGUSR2');
});
});
Below code works properly in Unix machine. Now, As your saveGame is asynchronous you have to call process.kill from within the callback.
process.once('SIGUSR2', function() {
setTimeout(()=>{
console.log('Shutting Down!');
process.kill(process.pid, 'SIGUSR2');
},3000);
});
So, your code looks fine as long as you execute your callback function from within the game.saveGame() function.
// Save game before restarting
process.once('SIGUSR2', function () {
console.log('SIGUR2');
game.saveGame(function() {
process.kill(process.pid, 'SIGUSR2');
});
});
on Windows
run app like this:
nodemon --signal SIGINT app.js
in app.js add code
let process = require('process');
process.once('SIGINT', function () {
console.log('SIGINT received');
your_func();
});
Consider this example given on the BrowserSync + Gulp page regarding Browser Reloading, especially this part:
// use default task to launch BrowserSync and watch JS files
gulp.task('default', ['browser-sync'], function () {
// add browserSync.reload to the tasks array to make
// all browsers reload after tasks are complete.
gulp.watch("js/*.js", ['js', browserSync.reload]);
});
As task dependencies are run asynchronously (here: the js and browserSync.reload) couldn't it happen that the reload finishes before the js task?
Yes, according to the documentation, that's a possibility.
Off that same page...
(make sure you return the stream from your tasks to ensure the browser is reloaded at the correct time)
If it's an async task it will just fire and not return anything, and the watcher will not know to refresh. Or it may reload before the process is done.
To get around this, you should be adding callbacks to your tasks.
gulp.task('somename', function() {
var stream = gulp.src('client/**/*.js')
.pipe(minify())
.pipe(gulp.dest('build'));
return stream;
});
Just return the stream so Gulp knows what is up. Then set the watch for the task you want:
gulp.task('default', ['browser-sync'], function () {
// Watched tasks are run in parallel, not in series.
gulp.watch(['*.js'], ['somename', browserSync.reload]);
});
This is all included in the documentation:
https://github.com/gulpjs/gulp/blob/master/docs/API.md#async-task-support
Once a Grunt task completes, I want to print out some information. See the Grunt snippet below.
Is there a way to achieve this? I noticed that grunt.task.run() does not support callbacks. This causes my message to be printed out prior to coverage report output.
grunt.registerTask('coverage', 'Runs all unit tests available via Mocha and generates code coverage report', function() {
grunt.task.run('env:unitTest', 'mochaTest');
grunt.log.writeln('Code coverage report was generated into "build/coverage.html"');
});
I also want to avoid "hacks" such as creating a grunt task only for printing the information out and adding it to the grunt.task.run() chain of tasks.
Create a task that will run when everything is all done and then add it to your task chain:
grunt.registerTask('alldone', function() {
grunt.log.writeln('Code coverage report was generated into "build/coverage.html"');
});
grunt.registerTask('default', ['env:unitTest', 'mochaTest', 'alldone']);
There is a much better way to do it, without creating an extra task, and modifying anything else.
Grunt is a node process, so you can:
use the process stdout to write what you need
subscribe to the process exit event to do it when a task is finishing its execution
This is a simple example which prints out the time when the tasks has finished their execution:
module.exports = function (grunt) {
// Creates a write function bound to process.stdout:
var write = process.stdout.write.bind(process.stdout);
// Subscribes to the process exit event...
process.on("exit", function () {
// ... to write the information in the process stdout
write('\nFinished at ' + new Date().toLocaleTimeString()+ '\n');
});
// From here, your usual gruntfile configuration, without changes
grunt.initConfig({
When you run any task, you'll see a message at the bottom like:
Finished at 18:26:45
I'm using grunt to have some tasks done every time I change my code ( jshint for example ) and I want to reload a phantomJs process every time I have changes.
The first way I found is to use grunt.util.spawn to run phantomJs the first time.
// http://gruntjs.com/api/grunt.util#grunt.util.spawn
var phantomJS_child = grunt.util.spawn({
cmd: './phantomjs-1.9.1-linux-x86_64/bin/phantomjs',
args: ['./phantomWorker.js']
},
function(){
console.log('phantomjs done!'); // we never get here...
});
And then, every time watch restarts, another task uses grunt.util.spawn to kill the phantomJs process, which is of course VERY ugly.
Is there any better way to do it?
The thing is that the phantomJs process is not teminating because I use it as a webserver to server a REST API with JSON.
Can I have a grunt callback or something whenever watch kicks in so I can close my previous phantomJs process before I re-run the task to create a new one?
I used grunt.event to make a handler, but I cannot see how to access the phantomjs process in order to kill it.
grunt.registerTask('onWatchEvent',function(){
// whenever watch starts, do this...
grunt.event.on('watch',function(event, file, task){
grunt.log.writeln('\n' + event + ' ' + file + ' | running-> ' + task);
});
});
This entirely untested code could be a solution for your problem.
Node's native child spawning function exec immediately returns a reference to the child process, which we can keep around to later kill it. To use it we can create a custom grunt task on the fly, like so:
// THIS DOESN'T WORK. phantomjs is undefined every time the watcher re-executes the task
var exec = require('child_process').exec,
phantomjs;
grunt.registerTask('spawn-phantomjs', function() {
// if there's already phantomjs instance tell it to quit
phantomjs && phantomjs.kill();
// (re-)start phantomjs
phantomjs = exec('./phantomjs-1.9.1-linux-x86_64/bin/phantomjs ./phantomWorker.js',
function (err, stdout, stderr) {
grunt.log.write(stdout);
grunt.log.error(stderr);
if (err !== null) {
grunt.log.error('exec error: ' + err);
}
});
// when grunt exits, make sure phantomjs quits too
process.on('exit', function() {
grunt.log.writeln('killing child...');
phantomjs.kill();
});
});