How can I clear timeout for an asynchronous function in JavaScript - javascript

Let me be very clear so as to avoid confusion.
I have a sleep function (below) which timeouts for as many millisecond as I specify.
function sleep(ms)
{
return new Promise(resolve => setTimeout(resolve, ms));
}
Now in another function beginTest() I called sleep for some millisecond let say 5000 ms.
async function beginTest()
{
await sleep(5000);
}
I have a separate function which gets executed when a button is clicked. I want the function to clear the timeout whenever the button is clicked before completion of 5000 ms. I understand that after 5000 ms clicking the button should not affect anything as the promise has already been resolved.
document.getElementById("reactTimeClick").onmousedown = function()
{
cleartimeOut(); // Clear timeout of above function
}

It's pretty simple to do as you propose with a "cancellation token" via which the "sleep timeout" can be cancelled:
// don't do this
function sleep(ms, cancellationToken) {
return new Promise(resolve => function() {
let timeoutRef = setTimeout(resolve, ms);
cancellationToken.cancel = function() {
clearTimout(timeoutRef);
};
});
}
However that will not, in itself, cause the sleep promise to depart from its pending state and the promise chain (or awaiting statements) stemming from sleep() will not be informed of the cancellation. Progress will hang.
This shortcoming can be overcome, again with a cancellation token, but this time one that allows the sleep() promise to be rejected, as follows ...
// do this
function sleep(ms, cancellationToken) {
return new Promise((resolve, reject) => function() {
cancellationToken.cancel = function() {
reject(new Error('sleep() cancelled'));
};
setTimeout(resolve, ms));
}
}
... and in the caller, use as follows:
async function beginTest() {
try {
const token = {};
const promise = sleep(5000, token);
$('#cancelButton').on('click', token.cancel); // jQuery example, or similar in POJS
await promise;
// ... test code ...
// ... return whatever;
}
catch(error) {
console.log(error.message);
// If button was clicked before the 5000 ms has expired,
// and no other error has been thrown,
// then the log will show "sleep() cancelled".
throw error; // rethrow error to keep beginTest's caller informed.
}
}

Related

How can I do I cancel javascript await sleep?

The most common implementation of a sleep function in javascript is returning a Promise after setTimeout resolves:
function sleep(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
I have for loop with await sleep to keep it from executing too fast, such as not requesting xhr too fast. I also have a isBreak flag elsewhere to tell me when to stop the for loop. However, the issue I have is that when I break the for loop, the previous await sleep has already executed and is holding up the for loop. Is there a better way of breaking the for loop and also terminating the await sleep instantaneously?
const items = [];
let isBreak = false; // Somewhere else in the application
for (const item of items) {
if (isBreak) break;
// Do something, like xhr request
await sleep(15000); // 15 seconds sleep
if (isBreak) break;
}
Is there a way for me to signal for early
In JS, when an await operation starts, it can no longer be interrupted; it will wait until its operand promise is settled.
So, you have to make the promise you're awaiting cancelable in some way.
Unfortunately, your code can't get notified about a variable reassignment (when you set isBreak to true), and polling it would be inefficient.
Instead of a flag, you could use an AbortSignal (which was invented for this purpose), and make your sleep accept one:
function sleep(ms, signal) {
return new Promise((resolve, reject) => {
signal.throwIfAborted();
const timeout = setTimeout(() => {
resolve();
signal.removeEventListener('abort', abort);
}, ms);
const abort = () => {
clearTimeout(timeout);
reject(signal.reason);
}
signal.addEventListener('abort', abort);
});
}
Then, you use it like this:
const items = [];
const isBreak = new AbortController(); // Somewhere else in the application, call `isBreak.abort()`
try {
for (const item of items) {
// Do something, like xhr request
await sleep(15000, isBreak.signal); // 15 seconds sleep
}
} catch (e) {
if (e.name === 'TimeoutError') {
// Handle a cancellation
console.log('Cancelled');
} else {
// Not a cancellation, rethrow it
throw e;
}
}
An AbortSignal works well with fetch as well, in case you have to cancel that too.
An answer i found in a blog in the past that i adjusted. It is similiar to FZs answer. Same usage, too. Just to give an alternative.
relevant too: How to cancel timeout inside of Javascript Promise?
function sleep(ms, abortSignal) {
return new Promise((resolve, reject) => {
signal.addEventListener("abort", abort);
if(abortSignal.aborted){
abort();
}
const timeout = setTimeout(end, ms);
function abort() {
clearTimeout(timeout);
abortSignal.removeEventListener("abort", abort);
reject(new Error("sleep aborted"));
}
function end() {
abortSignal.removeEventListener("abort", abort);
resolve();
}
});
}

Notification.requestPermission promise is never resolved if user has quieter messaging enabled

We have a slider button on our site where users can opt in to browser push notifications. We recently noticed that the chromium feature "quieter messaging" causes some issues in our implementation. We always evaluated the returned promise of requestPermission to tell the user if their action actually worked. However, if the setting is enabled, the promise is never resolved(or rejected) unless the user clicks on "allow".
async function init() {
var permission = await Notification.requestPermission();
alert(permission); // This is never called in this case
}
init();
We want to tell the user if their action (enabling the notifications) actually worked, or if they need to check their browser settings. Is there a better way than having a separate timeout promise?
This is my current best guess for a workaround:
// https://italonascimento.github.io/applying-a-timeout-to-your-promises/
const promiseTimeout = function (ms, promise) {
// Create a promise that rejects in <ms> milliseconds
let timeout = new Promise((resolve, reject) => {
let id = setTimeout(() => {
clearTimeout(id);
reject('Timed out in ' + ms + 'ms.')
}, ms)
})
// Returns a race between our timeout and the passed in promise
return Promise.race([
promise,
timeout
])
}
async function init() {
var permissionPromise = Notification.requestPermission();
try {
var p = await promiseTimeout(1000/*some magic number*/, permissionPromise);
alert(p);
} catch (error) {
alert(error);
}
}
init();
Posting my workaround as an answer since there seems to be no better other solution at this point.
// https://italonascimento.github.io/applying-a-timeout-to-your-promises/
const promiseTimeout = function (ms, promise) {
// Create a promise that rejects in <ms> milliseconds
let timeout = new Promise((resolve, reject) => {
let id = setTimeout(() => {
clearTimeout(id);
reject('Timed out in ' + ms + 'ms.')
}, ms)
})
// Returns a race between our timeout and the passed in promise
return Promise.race([
promise,
timeout
])
}
async function init() {
var permissionPromise = Notification.requestPermission();
try {
var p = await promiseTimeout(1000/*some magic number*/, permissionPromise);
alert(p);
} catch (error) {
alert(error);
}
}
init();

How can I return a error if response not received in 1 minute (NodeJs)

First thing to note I'm using node version of 6.15.
Here I have a promise method which will return response upon calling an function.
myFunction: (params) = {
return innerFunction(params)
.then((resp) => {
return resp })
.catch((err) => {
throw err })
}
Here the challenge is innerFunction sometime will take more time to give response, so I need to return this function as an error if response doesn't received in 1 minute
How can I achieve that?
This is simply achieved with static method Promise.race(). All you have to do is race the promise returned by innerFunction() against a promisified timeout that settles to an Error.
if innerFunction() wins the race, then its result/Error will be delivered.
if the promisified timeout wins the race, then its Error will be delivered.
In other words, Promise.race() is transparent to whichever promise wins the race and opaque to the other.
myFunction: (params) = {
let timeoutPromise = new Promise((_, reject) => {
setTimeout(reject, 60000, new Error('timed out'));
});
return Promise.race([timeoutPromise, innerFunction(params)]); // race two promises against each other.
}
For flexibility, you might choose to pass the timeout duration to the function, and allow a zero value to mean no timeout.
myFunction: (params, timeoutDuration = 0) = {
if(timeoutDuration > 0) {
let timeoutPromise = new Promise((_, reject) => {
setTimeout(reject, timeoutDuration, new Error('timed out'));
});
return Promise.race([timeoutPromise, innerFunction(params)]); // race two promises against each other.
} else {
return innerFunction(params);
}
}
For a simple solution, I would use the bluebird#timeout method! (more about this here)
Here is a short example, how to use it:
// import the library
const Bluebird = require('bluebird')
// timeout needs the duration parameter in milliseconds
const TIMEOUT_IN_MS = 60000; // 1 min
// if you use the native promise, you must wrap it first
// it returns a promise compatible with the native promise
Promise.resolve(innerFunction(params)).timeout(TIMEOUT_IN_MS)

Force stop function execution [duplicate]

How to implement a timeout in Javascript, not the window.timeout but something like session timeout or socket timeout - basically - a "function timeout"
A specified period of time that will be allowed to elapse in a system
before a specified event is to take place, unless another specified
event occurs first; in either case, the period is terminated when
either event takes place.
Specifically, I want a javascript observing timer that will observe the execution time of a function and if reached or going more than a specified time then the observing timer will stop/notify the executing function.
Any help is greatly appreciated! Thanks a lot.
I'm not entirely clear what you're asking, but I think that Javascript does not work the way you want so it cannot be done. For example, it cannot be done that a regular function call lasts either until the operation completes or a certain amount of time whichever comes first. That can be implemented outside of javascript and exposed through javascript (as is done with synchronous ajax calls), but can't be done in pure javascript with regular functions.
Unlike other languages, Javascript is single threaded so that while a function is executing a timer will never execute (except for web workers, but they are very, very limited in what they can do). The timer can only execute when the function finishes executing. Thus, you can't even share a progress variable between a synchronous function and a timer so there's no way for a timer to "check on" the progress of a function.
If your code was completely stand-alone (didn't access any of your global variables, didn't call your other functions and didn't access the DOM in anyway), then you could run it in a web-worker (available in newer browsers only) and use a timer in the main thread. When the web-worker code completes, it sends a message to the main thread with it's results. When the main thread receives that message, it stops the timer. If the timer fires before receiving the results, it can kill the web-worker. But, your code would have to live with the restrictions of web-workers.
Soemthing can also be done with asynchronous operations (because they work better with Javascript's single-threaded-ness) like this:
Start an asynchronous operation like an ajax call or the loading of an image.
Start a timer using setTimeout() for your timeout time.
If the timer fires before your asynchronous operation completes, then stop the asynchronous operation (using the APIs to cancel it).
If the asynchronous operation completes before the timer fires, then cancel the timer with clearTimeout() and proceed.
For example, here's how to put a timeout on the loading of an image:
function loadImage(url, maxTime, data, fnSuccess, fnFail) {
var img = new Image();
var timer = setTimeout(function() {
timer = null;
fnFail(data, url);
}, maxTime);
img.onLoad = function() {
if (timer) {
clearTimeout(timer);
fnSuccess(data, img);
}
}
img.onAbort = img.onError = function() {
clearTimeout(timer);
fnFail(data, url);
}
img.src = url;
}
My question has been marked as a duplicate of this one so I thought I'd answer it even though the original post is already nine years old.
It took me a while to wrap my head around what it means for Javascript to be single-threaded (and I'm still not sure I understood things 100%) but here's how I solved a similar use-case using Promises and a callback. It's mostly based on this tutorial.
First, we define a timeout function to wrap around Promises:
const timeout = (prom, time, exception) => {
let timer;
return Promise.race([
prom,
new Promise((_r, rej) => timer = setTimeout(rej, time, exception))
]).finally(() => clearTimeout(timer));
}
This is the promise I want to timeout:
const someLongRunningFunction = async () => {
...
return ...;
}
Finally, I use it like this.
const TIMEOUT = 2000;
const timeoutError = Symbol();
var value = "some default value";
try {
value = await timeout(someLongRunningFunction(), TIMEOUT, timeoutError);
}
catch(e) {
if (e === timeoutError) {
console.log("Timeout");
}
else {
console.log("Error: " + e);
}
}
finally {
return callback(value);
}
This will call the callback function with the return value of someLongRunningFunction or a default value in case of a timeout. You can modify it to handle timeouts differently (e.g. throw an error).
You could execute the code in a web worker. Then you are still able to handle timeout events while the code is running. As soon as the web worker finishes its job you can cancel the timeout. And as soon as the timeout happens you can terminate the web worker.
execWithTimeout(function() {
if (Math.random() < 0.5) {
for(;;) {}
} else {
return 12;
}
}, 3000, function(err, result) {
if (err) {
console.log('Error: ' + err.message);
} else {
console.log('Result: ' + result);
}
});
function execWithTimeout(code, timeout, callback) {
var worker = new Worker('data:text/javascript;base64,' + btoa('self.postMessage((' + String(code) + '\n)());'));
var id = setTimeout(function() {
worker.terminate();
callback(new Error('Timeout'));
}, timeout);
worker.addEventListener('error', function(e) {
clearTimeout(id);
callback(e);
});
worker.addEventListener('message', function(e) {
clearTimeout(id);
callback(null, e.data);
});
}
I realize this is an old question/thread but perhaps this will be helpful to others.
Here's a generic callWithTimeout that you can await:
export function callWithTimeout(func, timeout) {
return new Promise((resolve, reject) => {
const timer = setTimeout(() => reject(new Error("timeout")), timeout)
func().then(
response => resolve(response),
err => reject(new Error(err))
).finally(() => clearTimeout(timer))
})
}
Tests/examples:
export function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
const func1 = async () => {
// test: func completes in time
await sleep(100)
}
const func2 = async () => {
// test: func does not complete in time
await sleep(300)
}
const func3 = async () => {
// test: func throws exception before timeout
await sleep(100)
throw new Error("exception in func")
}
const func4 = async () => {
// test: func would have thrown exception but timeout occurred first
await sleep(300)
throw new Error("exception in func")
}
Call with:
try {
await callWithTimeout(func, 200)
console.log("finished in time")
}
catch (err) {
console.log(err.message) // can be "timeout" or exception thrown by `func`
}
You can achieve this only using some hardcore tricks. Like for example if you know what kind of variable your function returns (note that EVERY js function returns something, default is undefined) you can try something like this: define variable
var x = null;
and run test in seperate "thread":
function test(){
if (x || x == undefined)
console.log("Cool, my function finished the job!");
else
console.log("Ehh, still far from finishing!");
}
setTimeout(test, 10000);
and finally run function:
x = myFunction(myArguments);
This only works if you know that your function either does not return any value (i.e. the returned value is undefined) or the value it returns is always "not false", i.e. is not converted to false statement (like 0, null, etc).
Here is my answer which essentially simplifies Martin's answer and is based upon the same tutorial.
Timeout wrapper for a promise:
const timeout = (prom, time) => {
const timeoutError = new Error(`execution time has exceeded the allowed time frame of ${time} ms`);
let timer; // will receive the setTimeout defined from time
timeoutError.name = "TimeoutErr";
return Promise.race([
prom,
new Promise((_r, rej) => timer = setTimeout(rej, time, timeoutError)) // returns the defined timeoutError in case of rejection
]).catch(err => { // handle errors that may occur during the promise race
throw(err);
}) .finally(() => clearTimeout(timer)); // clears timer
}
A promise for testing purposes:
const fn = async (a) => { // resolves in 500 ms or throw an error if a == true
if (a == true) throw new Error('test error');
await new Promise((res) => setTimeout(res, 500));
return "p2";
}
Now here is a test function:
async function test() {
let result;
try { // finishes before the timeout
result = await timeout(fn(), 1000); // timeouts in 1000 ms
console.log('• Returned Value :', result, '\n'); // result = p2
} catch(err) {
console.log('• Captured exception 0 : \n ', err, '\n');
}
try { // don't finish before the timeout
result = await timeout(fn(), 100); // timeouts in 100 ms
console.log(result); // not executed as the timeout error was triggered
} catch (err) {
console.log('• Captured exception 1 : \n ', err, '\n');
}
try { // an error occured during fn execution time
result = await timeout(fn(true), 100); // fn will throw an error
console.log(result); // not executed as an error occured
} catch (err) {
console.log('• Captured exception 2 : \n ', err, '\n');
}
}
that will produce this output:
• Returned Value : p2
• Captured exception 1 :
TimeoutErr: execution time has exceeded the allowed time frame of 100 ms
at C:\...\test-promise-race\test.js:33:34
at async test (C:\...\test-promise-race\test.js:63:18)
• Captured exception 2 :
Error: test error
at fn (C:\...\test-promise-race\test.js:45:26)
at test (C:\...\test-promise-race\test.js:72:32)
If you don't want to use try ... catch instructions in the test function you can alternatively replace the throw instructions in the catch part of the timeout promise wrapper by return.
By doing so the result variable will receive the error that is throwed otherwise. You can then use this to detect if the result variable actually contains an error.
if (result instanceof Error) {
// there was an error during execution
}
else {
// result contains the value returned by fn
}
If you want to check if the error is relative to the defined timeout you will have to check the error.name value for "TimeoutErr".
Share a variable between the observing timer and the executing function.
Implement the observing timer with window.setTimeout or window.setInterval. When the observing timer executes, it sets an exit value to the shared variable.
The executing function constantly checks for the variable value.. and returns if the exit value is specified.

How to implement a "function timeout" in Javascript - not just the 'setTimeout'

How to implement a timeout in Javascript, not the window.timeout but something like session timeout or socket timeout - basically - a "function timeout"
A specified period of time that will be allowed to elapse in a system
before a specified event is to take place, unless another specified
event occurs first; in either case, the period is terminated when
either event takes place.
Specifically, I want a javascript observing timer that will observe the execution time of a function and if reached or going more than a specified time then the observing timer will stop/notify the executing function.
Any help is greatly appreciated! Thanks a lot.
I'm not entirely clear what you're asking, but I think that Javascript does not work the way you want so it cannot be done. For example, it cannot be done that a regular function call lasts either until the operation completes or a certain amount of time whichever comes first. That can be implemented outside of javascript and exposed through javascript (as is done with synchronous ajax calls), but can't be done in pure javascript with regular functions.
Unlike other languages, Javascript is single threaded so that while a function is executing a timer will never execute (except for web workers, but they are very, very limited in what they can do). The timer can only execute when the function finishes executing. Thus, you can't even share a progress variable between a synchronous function and a timer so there's no way for a timer to "check on" the progress of a function.
If your code was completely stand-alone (didn't access any of your global variables, didn't call your other functions and didn't access the DOM in anyway), then you could run it in a web-worker (available in newer browsers only) and use a timer in the main thread. When the web-worker code completes, it sends a message to the main thread with it's results. When the main thread receives that message, it stops the timer. If the timer fires before receiving the results, it can kill the web-worker. But, your code would have to live with the restrictions of web-workers.
Soemthing can also be done with asynchronous operations (because they work better with Javascript's single-threaded-ness) like this:
Start an asynchronous operation like an ajax call or the loading of an image.
Start a timer using setTimeout() for your timeout time.
If the timer fires before your asynchronous operation completes, then stop the asynchronous operation (using the APIs to cancel it).
If the asynchronous operation completes before the timer fires, then cancel the timer with clearTimeout() and proceed.
For example, here's how to put a timeout on the loading of an image:
function loadImage(url, maxTime, data, fnSuccess, fnFail) {
var img = new Image();
var timer = setTimeout(function() {
timer = null;
fnFail(data, url);
}, maxTime);
img.onLoad = function() {
if (timer) {
clearTimeout(timer);
fnSuccess(data, img);
}
}
img.onAbort = img.onError = function() {
clearTimeout(timer);
fnFail(data, url);
}
img.src = url;
}
My question has been marked as a duplicate of this one so I thought I'd answer it even though the original post is already nine years old.
It took me a while to wrap my head around what it means for Javascript to be single-threaded (and I'm still not sure I understood things 100%) but here's how I solved a similar use-case using Promises and a callback. It's mostly based on this tutorial.
First, we define a timeout function to wrap around Promises:
const timeout = (prom, time, exception) => {
let timer;
return Promise.race([
prom,
new Promise((_r, rej) => timer = setTimeout(rej, time, exception))
]).finally(() => clearTimeout(timer));
}
This is the promise I want to timeout:
const someLongRunningFunction = async () => {
...
return ...;
}
Finally, I use it like this.
const TIMEOUT = 2000;
const timeoutError = Symbol();
var value = "some default value";
try {
value = await timeout(someLongRunningFunction(), TIMEOUT, timeoutError);
}
catch(e) {
if (e === timeoutError) {
console.log("Timeout");
}
else {
console.log("Error: " + e);
}
}
finally {
return callback(value);
}
This will call the callback function with the return value of someLongRunningFunction or a default value in case of a timeout. You can modify it to handle timeouts differently (e.g. throw an error).
You could execute the code in a web worker. Then you are still able to handle timeout events while the code is running. As soon as the web worker finishes its job you can cancel the timeout. And as soon as the timeout happens you can terminate the web worker.
execWithTimeout(function() {
if (Math.random() < 0.5) {
for(;;) {}
} else {
return 12;
}
}, 3000, function(err, result) {
if (err) {
console.log('Error: ' + err.message);
} else {
console.log('Result: ' + result);
}
});
function execWithTimeout(code, timeout, callback) {
var worker = new Worker('data:text/javascript;base64,' + btoa('self.postMessage((' + String(code) + '\n)());'));
var id = setTimeout(function() {
worker.terminate();
callback(new Error('Timeout'));
}, timeout);
worker.addEventListener('error', function(e) {
clearTimeout(id);
callback(e);
});
worker.addEventListener('message', function(e) {
clearTimeout(id);
callback(null, e.data);
});
}
I realize this is an old question/thread but perhaps this will be helpful to others.
Here's a generic callWithTimeout that you can await:
export function callWithTimeout(func, timeout) {
return new Promise((resolve, reject) => {
const timer = setTimeout(() => reject(new Error("timeout")), timeout)
func().then(
response => resolve(response),
err => reject(new Error(err))
).finally(() => clearTimeout(timer))
})
}
Tests/examples:
export function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
const func1 = async () => {
// test: func completes in time
await sleep(100)
}
const func2 = async () => {
// test: func does not complete in time
await sleep(300)
}
const func3 = async () => {
// test: func throws exception before timeout
await sleep(100)
throw new Error("exception in func")
}
const func4 = async () => {
// test: func would have thrown exception but timeout occurred first
await sleep(300)
throw new Error("exception in func")
}
Call with:
try {
await callWithTimeout(func, 200)
console.log("finished in time")
}
catch (err) {
console.log(err.message) // can be "timeout" or exception thrown by `func`
}
You can achieve this only using some hardcore tricks. Like for example if you know what kind of variable your function returns (note that EVERY js function returns something, default is undefined) you can try something like this: define variable
var x = null;
and run test in seperate "thread":
function test(){
if (x || x == undefined)
console.log("Cool, my function finished the job!");
else
console.log("Ehh, still far from finishing!");
}
setTimeout(test, 10000);
and finally run function:
x = myFunction(myArguments);
This only works if you know that your function either does not return any value (i.e. the returned value is undefined) or the value it returns is always "not false", i.e. is not converted to false statement (like 0, null, etc).
Here is my answer which essentially simplifies Martin's answer and is based upon the same tutorial.
Timeout wrapper for a promise:
const timeout = (prom, time) => {
const timeoutError = new Error(`execution time has exceeded the allowed time frame of ${time} ms`);
let timer; // will receive the setTimeout defined from time
timeoutError.name = "TimeoutErr";
return Promise.race([
prom,
new Promise((_r, rej) => timer = setTimeout(rej, time, timeoutError)) // returns the defined timeoutError in case of rejection
]).catch(err => { // handle errors that may occur during the promise race
throw(err);
}) .finally(() => clearTimeout(timer)); // clears timer
}
A promise for testing purposes:
const fn = async (a) => { // resolves in 500 ms or throw an error if a == true
if (a == true) throw new Error('test error');
await new Promise((res) => setTimeout(res, 500));
return "p2";
}
Now here is a test function:
async function test() {
let result;
try { // finishes before the timeout
result = await timeout(fn(), 1000); // timeouts in 1000 ms
console.log('• Returned Value :', result, '\n'); // result = p2
} catch(err) {
console.log('• Captured exception 0 : \n ', err, '\n');
}
try { // don't finish before the timeout
result = await timeout(fn(), 100); // timeouts in 100 ms
console.log(result); // not executed as the timeout error was triggered
} catch (err) {
console.log('• Captured exception 1 : \n ', err, '\n');
}
try { // an error occured during fn execution time
result = await timeout(fn(true), 100); // fn will throw an error
console.log(result); // not executed as an error occured
} catch (err) {
console.log('• Captured exception 2 : \n ', err, '\n');
}
}
that will produce this output:
• Returned Value : p2
• Captured exception 1 :
TimeoutErr: execution time has exceeded the allowed time frame of 100 ms
at C:\...\test-promise-race\test.js:33:34
at async test (C:\...\test-promise-race\test.js:63:18)
• Captured exception 2 :
Error: test error
at fn (C:\...\test-promise-race\test.js:45:26)
at test (C:\...\test-promise-race\test.js:72:32)
If you don't want to use try ... catch instructions in the test function you can alternatively replace the throw instructions in the catch part of the timeout promise wrapper by return.
By doing so the result variable will receive the error that is throwed otherwise. You can then use this to detect if the result variable actually contains an error.
if (result instanceof Error) {
// there was an error during execution
}
else {
// result contains the value returned by fn
}
If you want to check if the error is relative to the defined timeout you will have to check the error.name value for "TimeoutErr".
Share a variable between the observing timer and the executing function.
Implement the observing timer with window.setTimeout or window.setInterval. When the observing timer executes, it sets an exit value to the shared variable.
The executing function constantly checks for the variable value.. and returns if the exit value is specified.

Categories

Resources