Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trouble setting timeout in node js

I have a domain exception handler (wrapper for nightwatch tests).

my exception handler wrapper

var domainError = function(func) {

    return function() {
      var d = domain.create().on('error', function(err) {
        console.error(err.stack);
      });

      d.enter();
      try {
        return func.apply(this, arguments);
      }
      catch (err) {
        //do something with the err
      }
      d.exit();
    }
};

I am trying to set timeouts so that return func.apply(this, arguments); doesn't take forever.

Could anyone suggest how I can add timeouts and make the domain end the function and exit, if it exceeds timeout?

like image 500
user461112 Avatar asked Apr 16 '15 10:04

user461112


People also ask

Why is setTimeout not working?

This is due to when a function is executed as a parameter to setTimeout , the execution context is different to the execution context of the function! Now this will print out undefined because the this keyword is executed in the context of the setTimeout function and is therefore not defined.

How do I increase server timeout in node JS?

For example, if you want to set request timeout to 200 seconds, then add the following line to server. js above. res. setTimeout(200);

What is the default timeout for Nodejs?

In Node. js, default server timeout is 0 milliseconds for the latest version and 2min i.e. (120000 milliseconds) for the older version.

Does setTimeout work in node JS?

The setTimeout function is used to call a function after the specified number of milliseconds. The delay of the called function begins after the remaining statements in the script have finished executing. The setTimeout function is found in the Timers module of Node. js.


1 Answers

This is impossible in Node's concurrency model. There are no "interrupts" - multiprocessing is done cooperatively. If you look at it from the other side - you get a really powerful guarantee that your code will almost always run to completion.

You can spawn another child process and then preempt that (since processes support preemption).


The easiest way to terminate a synchronous function is to execute it in its own "isolate" - meaning it can be killed. Note that this is not as performant as making a dedicated worker "process" and using async io to communicate with it - which is probably faster - but this is easier.

var vm = require('vm'); // get the VM module

// when you want to run a bit 
function withError(func, context, timeout){
     var ctx = vm.createContext(context);
     var code = func.toString().slice(12).slice(0,-2)
     return vm.runInContext(code, ctx, {
        timeout: timeout,
        displayErrors: true; // to log, like in your version
     });
}

Note that this code means the function has no access to closure scope or arguments, so everything needs to be in its scope - it's not as big of an issue as you might think since you can convert:

function doFoo(x, y){
    return x + y + z; // z is from closure
}

Into

function doFoo(){
    return this.x + this.y + this.z;
}

And call it as

withError(doFoo, {x:x, y:y, z:z }, 2000); // 2000 ms timeout

This can also be better automated by using a lexical analysis tool that generates a syntax tree.

If I may suggest an alternative - write your func in a way that it can yield control - cooperative multitasking is a lot easier and less error prone in these cases.

like image 53
Benjamin Gruenbaum Avatar answered Nov 15 '22 12:11

Benjamin Gruenbaum