1

I tried below function use co and javascript promise test, the fulfill will success return but reject not, and catch error undefined. and the flow can't continue. why?

Error:

> at GeneratorFunctionPrototype.next (native)
    at onFulfilled (/Users/../project/app/node_modules/co/index.js:65:19)
    at runMicrotasksCallback (node.js:337:7)
    at process._tickDomainCallback (node.js:381:11)

Code:

domain.run(function() {

  var testPromise = function() {
    return new Promise(function (fulfill, reject){
      //reject('error');
      reject(new Error('message'));
    });
  };


co(function *() {
  var d = yield testPromise();
  console.log(d);
  res.send('fin');
}).catch(onerror);
function onerror(error) { console.error(error.stack); }

});
domain.on('error', function(error) { console.error(error); });
Henrique Barcelos
  • 7,670
  • 1
  • 41
  • 66
user1775888
  • 3,147
  • 13
  • 45
  • 65
  • Is the `reject` argument itself undefined? Or is it perhaps because you passed a string to `reject()`, which doesn't have a `.stack` property (as referenced later in your code)? – greim Aug 25 '15 at 23:06
  • 1
    You should always pass an Error object to the rejection handler. Either an existing error object or a `new Error('blah blah')` – greim Aug 25 '15 at 23:07
  • if I remove the `catch` the function promise still same , can't move to next function – user1775888 Aug 25 '15 at 23:07
  • Don't remove the catch. Instead, do `reject(new Error('error'))` in the above code. See what I mean? – greim Aug 25 '15 at 23:09
  • I edit but my problem is the function is not keep moving to next just stop – user1775888 Aug 25 '15 at 23:12
  • So once you do that, do you not see a proper stack trace appear in the error console? – greim Aug 25 '15 at 23:12
  • I see. `yield testPromise()` throws an error. You'll need to wrap try/catch around it, in order for lines of code immediately below it to run. Then if you do that, your `onerror` function shouldn't ever be called. – greim Aug 25 '15 at 23:14
  • @greim but I wrap my code with `domain` – user1775888 Aug 25 '15 at 23:16

1 Answers1

7

catch error undefined

No. It catches the error 'error', the value you rejected with. Of course, it's not really an Error but a string, and as such it does not have a .stack property - that's why it logs undefined. Fix your code by doing

reject(new Error('…'));

See also Should a Promise.reject message be wrapped in Error?

the flow can't continue. why?

Well, because you've got an error, and thrown exceptions do have this behaviour. You'll also want to send a response in your error handler!

co(function *() {
  …
}).catch(function onerror(error) {
  console.error(error.stack);
  res.send('err');
});

Or if you intend to continue the flow at the call, put the .catch handler right there:

co(function *() {
  yield testPromise().then(function(d) {
    console.log(d);
  }).catch(function(error) {
    console.error(error.stack);
  });
  res.send('fin');
});

Alternatively, wrap your promise call in a try-catch:

co(function *() {
  try {
    var d = yield testPromise();
    console.log(d);
  } catch(error) {
    console.error(error.stack);
  }
  res.send('fin');
});
Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • I edit but my problem is the function is not keep moving to next just stop – user1775888 Aug 25 '15 at 23:12
  • So? Domains don't continue the flow either. I'm not sure where your misconception lies. – Bergi Aug 25 '15 at 23:17
  • @user1775888: What is the expected result? How did you think your code would work? – Bergi Aug 25 '15 at 23:18
  • I update the question, so the domain can't replace try catch? – user1775888 Aug 25 '15 at 23:19
  • @user1775888: Well, not if you need the `catch` *in* your flow. Btw, I don't see any reason to use domains here, promise callbacks (and `co`) are already throw-safe. – Bergi Aug 25 '15 at 23:22
  • my expected result is browser print fin, I tried add try catch it works, but if remove the try catch it stops, not execute after the promise , so I still have to add try catch in my code right?wrap with domain can't resolve this? – user1775888 Aug 25 '15 at 23:25
  • No, you just would have to put `res.send('err')` in your `onerror` function. – Bergi Aug 25 '15 at 23:28
  • it just test there other function after, and I tried to execute all done then render to browser – user1775888 Aug 25 '15 at 23:29
  • Yes, for that you'll have to catch each error individually. Either using `try catch` in your `co` generator, or by adding a `.catch(…)` handler on each promise. – Bergi Aug 25 '15 at 23:31
  • the `catch` after `co` can't get all inside the `co` wrap? , so maybe I should change the reject to fulfill too? to make it continue the flow – user1775888 Aug 25 '15 at 23:31
  • 1
    Well if you didn't intend to create an error, of course you shouldn't reject the promise in the first place. Not sure why you did that at all? – Bergi Aug 25 '15 at 23:35
  • Can you show me example how to add catch after the `testPromise` should I chain after the `return new Promise ... }).catch({ ... });` – user1775888 Aug 25 '15 at 23:39