Await does not catch error

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!
Daniel NiklausAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Daniel NiklausAuthor 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?
leakim971MultitechnicianCommented:
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

Julian HansenCommented:
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.
Exploring SharePoint 2016

Explore SharePoint 2016, the web-based, collaborative platform that integrates with Microsoft Office to provide intranets, secure document management, and collaboration so you can develop your online and offline capabilities.

Daniel NiklausAuthor 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?
Julian HansenCommented:
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

leakim971MultitechnicianCommented:
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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Daniel NiklausAuthor Commented:
thanks
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Node.js

From novice to tech pro — start learning today.