#188·co

Consistent stack traces

Author: madbenceCreated Jan 14, 2015Updated Jun 3, 2017

My problem is that if my Error is not created in the context of the generator, the stack trace is missing:

javascript
var co = require('co');

function* a() {
  yield* b();
}

function* b() {
  yield new Promise(function(resolve, reject) {
    setTimeout(function() {
      reject(new Error());
    }, 1000);
  });
}

co(function* () {
  try {
    yield* a();
  } catch(err) {
    console.error(err.stack);
  }
});
Error
    at null._onTimeout (...)
    at Timer.listOnTimeout (...)

Stack trace is just fine, if I throw in the generator:

javascript
var co = require('co');

function* a() {
  yield* b();
}

function* b() {
  yield new Promise(function(resolve, reject) {
    setTimeout(function() {
      resolve();
    }, 1000);
  });
  throw new Error();
}

co(function* () {
  try {
    yield* a();
  } catch(err) {
    console.error(err.stack);
  }
});
Error
    at b (...)
    at GeneratorFunctionPrototype.next (...)
    at a (...)
    at GeneratorFunctionPrototype.next (...)
    at ...
    at GeneratorFunctionPrototype.next (...)
    at onFulfilled (...)

I perfectly understand that this is the correct behavior (the setTimeouts callback has absolutely no idea that the computation was suspended), but it is really annoying. Is there any other way to fix this other than wrapping every Promise in a try-catch, and wrapping the original Error with a new one?

javascript
try {
  yield new Promise(function(resolve, reject) {
    setTimeout(function() {
      reject(new Error())
    }, 1000);
  });
} catch(e) {
  var err = new Error(e.message);
  err.original = e;
  throw err;
}