21

If I type debugger and I want to check something. But call to that function returns a promise, then i am stuck.

For example:

I typed debugger and it stopped.

function test(db) {
    debugger;
    // here i want to see something
    var a = .....;
}

But if I type

let d = db.User.create(); 

I'll get

Promise { pending }

now there is no recourse. I can't simply evaluate promise. Kinda make whole debugger less useful.

This would have been no problem, if it was synchronous, I'd have been able to jump in mid program, check out few things and modify program to my liking then run rest of the program.

Charlie
  • 22,886
  • 11
  • 59
  • 90
Muhammad Umer
  • 17,263
  • 19
  • 97
  • 168
  • 1
    Well if the promise does not have a result yet, you cannot evaluate it. You need to let the code resume to fulfill the promise. – Bergi Mar 03 '18 at 10:28
  • 1
    What is `d`? Where are yo calling `test`? – Bergi Mar 03 '18 at 10:28
  • suppose test is called somewhere in program flow, point is debugger gets called. Then in console you type `db.User.Create()` which returns a promise. – Muhammad Umer Mar 03 '18 at 18:51
  • Well, no, you cannot get an asynchronous result from anything while being paused at a breakpoint. – Bergi Mar 03 '18 at 19:01
  • https://nodejs.org/api/cli.html#cli_experimental_repl_await – Muhammad Umer Jun 04 '19 at 16:09
  • @MuhammadUmer does it work for you when 'debugger;' is set? For me it doesn't – Evmorov Jun 07 '19 at 07:45
  • start node with that flag, make sure version is > 10.xyz whatever it says there... paste this `p = new Promise((r,e)=> r(3),()=>3) result = await p; console.log(result)` I get 3 in result – Muhammad Umer Jun 07 '19 at 16:46
  • @MuhammadUmer, it works in `node repl`. But your question is about `debugger;`. When the code is stopped on a breakpoint then async code doesn't work - `Promise {}` is returned. – Evmorov Jun 08 '19 at 15:56
  • 1
    chrome supports async debugging, so if you debug using chrome dev tools and --inspect flag on nodejs you can do async debugging – Muhammad Umer Feb 06 '20 at 07:25
  • using async/await syntax should be helpful. – laxman Feb 12 '20 at 06:15
  • @MuhammadUmer, do you mean that your example now works with the latest dev tools and with the --inspect flag in nodejs? I'm trying to debug something similar like you did in your question and I can't. Did you enable something? – mihai Jan 25 '22 at 13:26
  • https://v8.dev/features/top-level-await and https://stackoverflow.com/a/65018201/1319799 (in nodejs top level works if you are using "module" type and version is > 13.3) – Muhammad Umer Jan 28 '22 at 16:31

5 Answers5

3

Probably in order to understand why promises can't be resolved while debugger is paused, you need to understand how Event Loop works. There are plenty of resources about it so no need to explain it here.

When you pause a Debugger, Event Loop gets paused too. And everything asynchronous is scheduled and handled in Event Loop.

Possible ways to resolve promise in debugger:

  • Somehow execute promise synchronously by pooling it manually. But as far as I checked, there is no way to do that. V8 doesn't give us that level of control. But maybe it can be achieved by writing Native Addon. Perhaps a function that accepts a promise and resolves it using V8's internals synchronously.
  • Create a new Web Worker or another process and execute the promise there. But you'd have to serialize the data and possibly recreate the state. Though it won't work anyways since creating and passing messages to new "thread" is asynchronous, so...

Unfortunately at the moment best and simplest ways I am aware of are:

  1. Print current state and use it to construct and execute code outside of the debugger.
  2. Assign result to a variable and continue(F5) debugger, so that your promise can be resolved. After use it as you'd like:
db.User.create().then(x => global.a = x);
// use global.a as you'd like:
console.log(global.a);
Binier
  • 1,047
  • 2
  • 11
  • 25
  • "*Somehow execute promise synchronously by pooling it manually*" - this makes no sense. A promise cannot be "executed". A promise doesn't know from where it gets resolved. You need to continue the entire process so that *the code that will resolve the promise* can run. – Bergi May 06 '20 at 18:18
  • @Bergi yes there currently is no way to achieve that because v8 doesnt provide such api and implementation. That is what I wrote. What you are saying is the way it is now. By creating addon we could possibly implement such functionality, if NApi provides enough low level control. – Binier May 06 '20 at 18:49
  • 1
    No, what I'm trying to say is that the functionality itself doesn't make sense. There can be no such addon. "*A function that accepts a promise and resolves it*" can easily be created, but it cannot resolve it with the value that the program would have produced. The only way to get the value that the OP wants is to resume the program. – Bergi May 06 '20 at 19:24
  • Functionality iteself doesn't make sense? how so? I am talking conceptually about possible solutions, not taking into account available api and implementation detail since I am not familiar with those. – Binier May 06 '20 at 20:15
  • And I am saying that it is not even conceptually possible. – Bergi May 06 '20 at 20:48
0

Use the debugger at the either event of the promise being resolved or rejected.

function test(db) {

   let d = db.User.create(); 

   d.then((result) => {
      debugger;
      ...
   },
   (e) => {
      debugger;
      ...
   })


}
Charlie
  • 22,886
  • 11
  • 59
  • 90
0

Chrome not too long ago launched async debugging in their Chrome Devtools. You need to enable the flag in chrome to use it for now.

Check out this nice article here - https://www.html5rocks.com/en/tutorials/developertools/async-call-stack/

Sohail
  • 4,506
  • 2
  • 38
  • 42
0

Please refer https://gist.github.com/martinheidegger/4c2b7908005f65f9a53b25d5fec65f63 check debug-promise.js module

'use strict'

var debug = require('./debug-promise')

debug.wrap(() => new Promise(() => {})).then(() => console.log('a executed'))
debug.wrap(() => Promise.resolve('x')).then(() => console.log('b executed'))


//
// This will output something like:
//
//   b executed
//   1 Promise is still unfullfilled!
//   --- (V347P-M6K) ---
//     at Object.<anonymous> (/debug-test2.js:5:7)
//     at Module._compile (module.js:571:32)
//     at Object.Module._extensions..js (module.js:580:10)
//   
//     CODE
//       () => new Promise(() => {})
//   
//   ---
//
Prashant Biradar
  • 301
  • 5
  • 14
0
const foo = async(db)=>{//just be sure that you are in async for this one

try{

let d = await db.User.create(); 
//now d is the result
}catch (err) {console.log(err)}

Or more basically

 db.User.create().then((data)=>console.log('user created',data))
                 .catch(err=>console.log('err'));

That's how you resolve promises. Don't forget to add the catch or you will have some trouble.