Await does not catch error

Daniel Niklaus
Daniel Niklaus used Ask the Experts™
on
Hi
Node.js
Calling the library https://github.com/naptha/tesseract.js#tesseractjs

We call the function worker.recognize(path2png, language) for OCR of a PNG in a await function.

async function readPNG(path2png, language) {
 const worker = new TesseractWorker();
 try{
   let result = await worker.recognize(path2png, language);
    return result.text;
 } catch (error) {
   console.error("************************** error=",error)
 } 
}

Open in new window


There is a crash in tesseract and we would expect that it lands in the catch(error), but it does not. Instead, we get this and no callback.

contains_unichar_id(unichar_id):Error:Assert failed:in file /src/src/ccutil/unicharset.h, line 502
trap!
trap!
abort("trap!"). Build with -s ASSERTIONS=1 for more info.
abort("trap!"). Build with -s ASSERTIONS=1 for more info.

/home/diego/NetBeansProjects/FromGitHub/tmp/localsearch_triage/node_modules/tesseract.js-core/tesseract-core.js:8
var Module=typeof TesseractCoreWASM!=="undefined"?TesseractCoreWASM:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}Module["arguments"]=[];Module["thisProgram"]="./this.program";Module["quit"]=(function(status,toThrow){throw toThrow});Module["preRun"]=[];Module["postRun"]=[];var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof require==="function"&&!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_WORKER;ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}else{retu
abort("abort(\"trap!\"). Build with -s ASSERTIONS=1 for more info."). Build with -s ASSERTIONS=1 for more info.

Open in new window


Thanks for your help!
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®

Author

Commented:
I figured out that I was missing the language for certain images. Now it does not crash. But still, I have a question to understand better "await" or "promise". To me it looks like I call tesseractjs, there is a crash on a C call within Tesseractjs, but the app is still running, so the "await" does not get an error (just waiting for the return).  Does my interpretation make sense?

And if so, can I escape an "await" with a timeout?
leakim971Multitechnician
Top Expert 2014

Commented:
Does my interpretation make sense?

this is the purpose of await, it wait the promise to be resolved and don't execute next line of code before

And if so, can I escape an "await" with a timeout?

Yes, you can use a "race" :
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/race
let result = await Promise.race([ 
	worker.recognize(path2png, language), 
	new Promise(function(resolve, reject) {
		setTimeout(function() {
			reject('fail');
		}, 1000); // wait 1s
	})
]);

Open in new window

Most Valuable Expert 2017
Distinguished Expert 2018

Commented:
As a matter of interest what are you expecting to happen on line 5 below.
async function readPNG(path2png, language) {
 const worker = new TesseractWorker();
 try{
   let result = await worker.recognize(path2png, language);
    return result.text;
 } catch (error) {
   console.error("************************** error=",error)
 } 
}

Open in new window

The return is going to return a promise - so what ever is consuming the readPNG return is going to have to wait on the return.

Consider this code
function waitForIt()
{
  return new Promise((res, rej) => {
    setTimeout(() => res('all done'), 2000);
  });
}

async function doit() {
  let result = await waitForIt();
  console.log('returning result');
  return result;
}
let res = doit();
console.log('Back from doit, res = ', res);
res.then(res => console.log(res));

Open in new window

Output is:
Immediate:
Back from doit, res =  
    Promise { "pending" }
    ​<state>: "pending"
​    <prototype>: PromiseProto { … }

Open in new window

And 2 seconds later
returning result
all done

Open in new window


Check that you are dealing with the return correctly.
Ensure you’re charging the right price for your IT

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden using our free interactive tool and use it to determine the right price for your IT services. Start calculating Now!

Author

Commented:
Thanks.
So, if something is crashing in await worker.recognize(path2png, language) and does not deliver me a return; it will not catch the error and waits. To escape the promise in case of a crash, I would use promise.race. Is that right?
Most Valuable Expert 2017
Distinguished Expert 2018

Commented:
Promise.race is only when you when you have a situation where 2 or more async tasks are in play and you want to stop when EITHER of them completes.
So if your worker is crashing and not resolving / rejecting the promise you can use a race to get around that but you would need to set your race condition high enough to not prematurely terminate your valid worker.

Have you tried using
worker.onerror = function() {
  // handle error here
}

Open in new window

Multitechnician
Top Expert 2014
Commented:
it will not catch the error

the error is happening until you fix it where it happening

To escape the promise in case of a crash, I would use promise.race. Is that right?

if you've no hand on the worker code, you can use the hack I proposed.


here some code to illustrate your scenario, I replaced the worker.recognize(path2png, language), by lines 2 to 8 below.
the first promise fail BUT the second finish and allow your code to continue.
just copy paste to the debugger console of your browser to see what happen

let result = await Promise.race([ 
	new Promise(function(resolve, reject) {
		setTimeout(function() {
			alert("first to finish but gonna fail");
			throw('error'); // for testing we simulate the crash here
			resolve('ok'); // so will never reach this line
		}, 900); // wait 900ms
	}),
	new Promise(function(resolve, reject) {
		setTimeout(function() {
			alert("the quicker code - 900ms - fail but we reach here");
			resolve('fail but result get a default value : this message'); // use reject instead  if you want to handle the fact it fail 
		}, 1000); // wait 1s
	})
]);
console.log("the value is : " + result);

Open in new window

Author

Commented:
thanks

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial