Is this possible to limit javascript function executing time? - javascript

I got a long javascript function, it may process a few second. But I would like to limit the javascript executing time, if it is longer than X second, whatever the executing result, the function will be killed. Is this possible to implement that in JS? Thanks.

I used promises to achieve this. I just started 2 promises: first is my function to be executed wrapper in promise, second is timeout promise - when operation consider to be failed and use reject in it.
Using Promise.race I just wait what action is completed first. If second - reject occurs, if first - my code completes successfully.
Here is example:
var p1 = new Promise((resolve, reject) => {
setTimeout(resolve, 2000, "long_execution");
});
var p2 = new Promise((resolve, reject) => {
setTimeout(resolve, 500, "ok");
});
var p3 = new Promise((resolve, reject) => {
setTimeout(reject, 1000, "reject");
});
Promise.race([p1, p3]).then(values => {
console.log(values);
}, reason => {
console.log(reason)
});
Promise.race([p2, p3]).then(values => {
console.log(values);
}, reason => {
console.log(reason)
});

JavaScript is a single threaded, so one need to use async mechanism to achieve what you're trying to do.
One way of doing this with a single promise with TimeOut. If timeout happens then you promise is Rejected and if not the Promise is resolved.
A Sample code may look something like
var PTest = function () {
return new Promise(function (resolve, reject) {
setTimeout(function() {
reject();
}, 2000)
// Lines of Code
resolve();
});
}
var myfunc = PTest();
myfunc.then(function () {
console.log("Promise Resolved");
}).catch(function () {
console.log("Promise Rejected");
});

Related

Javascript Promise chaining not working as expected

I am trying to return a promise inside a promise but cannot get it to work
Here is my code
async function main() {
return new Promise((resolve, reject) => {
p = new Promise((resolve, reject) => {
f2(async() => {
resolve();
});
});
array = [];
array.push(p);
Promise.all(array).then(resolve(1));
});
}
setTimeout(async() => {
console.log(await main());
}, 0);
function f2(callback) {
console.log("h called");
setTimeout(() => {
callback();
}, 4000);
}
I expect that he array will be resolved after the timeout in f2() but it is resolving instantly.
Any help will be appreciated
The resolve function is being called right away, try something like this:
Promise.all(array).then(() => {
resolve(1);
});
Edit: I wanted to add that what is passed to the then() callback of a promise is a statement, using resolve(1) is a call to execute that code, but by wrapping that function call in an anonymous function declaration, the entire function declaration is passed, and then called when needed.

Promise.all Replacement?

Is there any way where I can call multiple async functions in Javascript, but get response of the call as soon as one completes, unlike Promise.all that waits for all async calls to complete?
What I want is, run async calls in parallel, and get response of a respective call as soon as it gets completed while other calls are still running and then update the react state.
I am already using Promise.all for multiple async calls, but it gives responses when all calls are finished.
You can just iterate over an array of promises and change the state on each promise resolution:
let state = null;
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve({p1: 1});
}, 2000);
});
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve({p2: 2});
}, 1000);
});
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve({p3: 3});
}, 3000);
});
// Iterate promises
[p1, p2, p3].forEach(p => {
p.then(res => {
state = Object.assign({}, state, res);
console.log(state);
});
});
console.log(state);
You could create your own Promise method for this task:
if (!Promise.each) {
Promise.each = function(promises, callback, error) {
if (promises && Array.isArray(promises)) {
promises.forEach(p => {
p.then(res => {
callback(res);
}, err => {
if (error) {
error(err);
} else {
console.log(err);
}
});
});
}
}
}
// Usage
Promise.each([p1, p2, p3], updateState);
In your question the phrase "than update ... state" is the key. You plan to update the state in such a way that as soon as one promise "completed" the corresponding state is updated. You have been trying something like this
async function f1(){ await Promise.resolve(); }
async funciton f2(){ await Promise.resolve(); }
async function fn(){ await Promise.resolve(); }
async function drvAsync(){
const [r1, r2, rn] = await Promise.all([f1(), f2(), fn()]);
u1(r1);
u2(r2);
un(rn);
}
where f[n] is an async business function, u[n] is a method to deal with the result from it. This schema is not acceptable in your scenario. Perhaps fn completes faster than others and you want to update N-th state earlier.
My recommendation is use no synchronization primitives at all. Instead you should deal with the results separately.
function drv(){
f1().then((r1)=>u1(r1)).catch((e)=>er(e));
f2().then((r2)=>u2(r2)).catch((e)=>er(e));
fn().then((rn)=>un(rn)).catch((e)=>er(e));;
}
This schema will call each update (u[n]) method without waiting results from others.
This is what Promise.race is for:
The Promise.race() method returns a promise that fulfills or rejects as soon as one of the promises in an iterable fulfills or rejects, with the value or reason from that promise.
For instance:
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function main() {
const promises = [
sleep(1000).then(() => "world"),
sleep(100).then(() => "hello"),
];
const promisesWithIndices = promises.map((p, index) =>
p.then((result) => ({result, index}))
);
while (promisesWithIndices.length > 0) {
const {result, index} = await Promise.race(promisesWithIndices);
console.log("%s -> %s", index, result);
promisesWithIndices.splice(index, 1);
}
}
main(); // prints "1 -> hello"; then prints "0 -> world" after a while
As long as you don't use async/await you can do the calls in parallel. Note that browsers have connection limit for network requests so if you execute for example 100 calls it will not be parallel but rather be queued.
You need a callback to execute when the promise resolved. If this callback is the same for all functions than just loop all calls, create the promise and resolve with the same function.
function resolved(data) {
// ...
}
const promise1 = new Promise(function(resolve, reject) {
resolve('Success!');
}).then(resolved);
const promise2 = new Promise(function(resolve, reject) {
resolve('Success!');
}).then(resolved);

Why do you need to use .then() methods with javascript Promises?

New to Web Dev and learning Javascript.
Ive been following a tutorial on Promises, to try and understand what they are used for and what is so useful about them, and I came across this code:
var isMomHappy = true;
// Promise
var willIGetNewPhone = new Promise(
function (resolve, reject) {
if (isMomHappy) {
var phone = {
brand: 'Samsung',
color: 'black'
};
resolve(phone);
} else {
var reason = new Error('mom is not happy');
reject(reason);
}
}
);
//call our promise
var askMom = function () {
willIGetNewPhone
.then(function (fulfilled) {
// yay, you got a new phone
console.log(fulfilled);
})
.catch(function (error) {
// ops, mom don't buy it
console.log(error.message);
});
}
askMom();
Why is the .then() method needed when calling and handling the promise?
Can I not just do the following:
var isMomHappy = false;
// Promise
var willIGetNewPhone = new Promise(
function (resolve, reject) {
if (isMomHappy) {
var phone = {
brand: 'Samsung',
color: 'black'
};
resolve(phone);
console.log(phone);
} else {
var reason = new Error('mom is not happy');
reject(reason);
console.log(reason.message);
}
}
)
willIGetNewPhone;
...as this seems to reproduce the same results?
Thanks,
Stu
Your example just doesn't represent the real deal here. A promise is useful when e.g. you deal with data that needs to load first.
Here is another example (that is still gibberish and not 100% what you do for real)
const myPromise = new Promise((resolve) => {
setTimeout(
() => resolve('hello promise'),
1000
);
});
myPromise.then((data) => console.log(data));
console.log('This is called after then, yet it was executed before the promise resolved');
As you can see, you don't have the data, that is resolved by the promise straight away, but need to wait for a second. Imagine, you try to get data from the server. It won't be available straight away. So instead, you need to wait until it is resolved.
With ES7, there is another syntax which might make it a bit more clear: async/await:
const myPromise = new Promise((resolve) => {
setTimeout(
() => resolve('hello promise'),
1000
);
});
const init = async() => {
const data = await myPromise; // wait until promise has resolved
console.log(data);
console.log('Now the code flow is "correct" in the readers view')
};
init();
The then method returns a Promise which allows for method chaining.
If the function passed as handler to then returns a Promise, an equivalent Promise will be exposed to the subsequent then in the method chain.
See it on the docs for more detail.
In a very simple term (speaking language):
Go to the restaurant (promise succeeded)
Then, have some refreshment.
If you don't (promise failed)
Then, you'll miss enjoyment.
the .then((result)=>{}) is asking for the promises value to be passed into the function.
Your promise example is a bit terrible, so here is a more relevant example
const doingStuff=new Promise(function(resolve, reject){
setTimeout(function(){
resolve('hello world');
}, 10000);
});
doingStuff.then(function(result){
console.log(result);
});
console.log('after hello world');
The callback in the .then is called with the timeout finishes. That's async. It also means your function in the timeout is no longer anonymous, if it errors, promises will clearly show the doingStuff promise errored.
If you run this, your console will say
after hello world
hello world
Backwards, that's because your then ran after 10 seconds, even though it appeared first in code.
If you try this code, the error will happen before the resolve.
const doingStuff=new Promise(function(resolve, reject){
setTimeout(function(){
resolve('hello world');
}, 10000);
setTimeout(function(){
reject(new Error('Something went wrong'));
},5000);
});
doingStuff.then(function(result){
console.log(result);
});
console.log('after hello world');
Your console log will show the exact location this went wrong. And even better, you can handle the error later, the promise will hold onto the error until your ready using .catch(function(e){});.
const doingStuff=new Promise(function(resolve, reject){
setTimeout(function(){
resolve('hello world');
}, 10000);
setTimeout(function(){
reject(new Error('Something went wrong'));
},5000);
});
doingStuff.then(function(result){
console.log(result);
}).catch(function(e){
console.log('Error message:', e.message);
});
console.log('after hello world');

What are some typical use-cases for `Promise.race()`? [duplicate]

As far as I know, there are two options about promise:
promise.all()
promise.race()
Ok, I know what promise.all() does. It runs promises in parallel, and .then gives you the values if both resolved successfully. Here is an example:
Promise.all([
$.ajax({ url: 'test1.php' }),
$.ajax({ url: 'test2.php' })
])
.then(([res1, res2]) => {
// Both requests resolved
})
.catch(error => {
// Something went wrong
});
But I don't understand what does promise.race() is supposed to do exactly? In other word, what's the difference with not using it? Assume this:
$.ajax({
url: 'test1.php',
async: true,
success: function (data) {
// This request resolved
}
});
$.ajax({
url: 'test2.php',
async: true,
success: function (data) {
// This request resolved
}
});
See? I haven't used promise.race() and it behaves like promise.race(). Anyway, is there any simple and clean example to show me when exactly should I use promise.race() ?
As you see, the race() will return the promise instance which is firstly resolved or rejected:
var p1 = new Promise(function(resolve, reject) {
setTimeout(resolve, 500, 'one');
});
var p2 = new Promise(function(resolve, reject) {
setTimeout(resolve, 100, 'two');
});
Promise.race([p1, p2]).then(function(value) {
console.log(value); // "two"
// Both resolve, but p2 is faster
});
For a scenes to be used, maybe you want to limit the cost time of a request :
var p = Promise.race([
fetch('/resource-that-may-take-a-while'),
new Promise(function (resolve, reject) {
setTimeout(() => reject(new Error('request timeout')), 5000)
})
])
p.then(response => console.log(response))
p.catch(error => console.log(error))
With the race() you just need to get the returned promise, you needn't care about which one of the promises in the race([]) firstly returned,
However, without the race, just like your example, you need to care about which one will firstly returned, and called the callback in the both success callback.
I've used it for request batching. We had to batch tens of thousands of records into batches for a long running execution. We could do it in parallel, but didn't want the number of pending requests to get out of hand.
Race lets us keep a fixed number of parallel promises running and add one to replace whenever one completes
const _ = require('lodash')
async function batchRequests(options) {
let query = { offset: 0, limit: options.limit };
do {
batch = await model.findAll(query);
query.offset += options.limit;
if (batch.length) {
const promise = doLongRequestForBatch(batch).then(() => {
// Once complete, pop this promise from our array
// so that we know we can add another batch in its place
_.remove(promises, p => p === promise);
});
promises.push(promise);
// Once we hit our concurrency limit, wait for at least one promise to
// resolve before continuing to batch off requests
if (promises.length >= options.concurrentBatches) {
await Promise.race(promises);
}
}
} while (batch.length);
// Wait for remaining batches to finish
return Promise.all(promises);
}
batchRequests({ limit: 100, concurrentBatches: 5 });
It's a piece to build a timeout system, where:
the request/computation may be canceled by another channel
it will still be used later, but we need an interaction now.
For an example of the second, one might show a spinner "instantly" while still defaulting to show real content if it comes in fast enough. Try running the below a few times - note at least some console message comes "instantly". This might normally be attached to perform operations on a UI.
The key to note is - the result of Promise.race is much less important than the side effects (though, this then is a code smell).
// 300 ms _feels_ "instant", and flickers are bad
function getUserInfo(user) {
return new Promise((resolve, reject) => {
// had it at 1500 to be more true-to-life, but 900 is better for testing
setTimeout(() => resolve("user data!"), Math.floor(900*Math.random()));
});
}
function showUserInfo(user) {
return getUserInfo().then(info => {
console.log("user info:", info);
return true;
});
}
function showSpinner() {
console.log("please wait...")
}
function timeout(delay, result) {
return new Promise(resolve => {
setTimeout(() => resolve(result), delay);
});
}
Promise.race([showUserInfo(), timeout(300)]).then(displayed => {
if (!displayed) showSpinner();
});
Inspiration credit to a comment by captainkovalsky.
An example of the first:
function timeout(delay) {
let cancel;
const wait = new Promise(resolve => {
const timer = setTimeout(() => resolve(false), delay);
cancel = () => {
clearTimeout(timer);
resolve(true);
};
});
wait.cancel = cancel;
return wait;
}
function doWork() {
const workFactor = Math.floor(600*Math.random());
const work = timeout(workFactor);
const result = work.then(canceled => {
if (canceled)
console.log('Work canceled');
else
console.log('Work done in', workFactor, 'ms');
return !canceled;
});
result.cancel = work.cancel;
return result;
}
function attemptWork() {
const work = doWork();
return Promise.race([work, timeout(300)])
.then(done => {
if (!done)
work.cancel();
return (done ? 'Work complete!' : 'I gave up');
});
}
attemptWork().then(console.log);
You can see from this one that the timeout's console.log is never executed when the timeout hits first. It should fail/succeed about half/half, for testing convenience.
Here's an easy example to understand the use of promise.race():
Imagine you need to fetch some data from a server and if the data takes too long to load (say 15 seconds) you want to show an error.
You would call promise.race() with two promises, the first being your ajax request and the second being a simple setTimeout(() => resolve("ERROR"), 15000)
Summary:
Promise.race is a JS built in function that accepts an iterable of Promises (e.g. Array) as an argument. This function then asynchronously returns a Promise as soon as one in of the Promises passed in the iterable is either resolved or rejected.
Example 1:
var promise1 = new Promise((resolve, reject) => {
setTimeout(() => resolve('Promise-one'), 500);
});
var promise2 = new Promise((resolve, reject) => {
setTimeout(() => resolve('Promise-two'), 100);
});
Promise.race([promise1, promise2]).then((value) => {
console.log(value);
// Both resolve, but promise2 is faster than promise 1
});
In this example first an array of Promises is passed in Promise.race. Both of the promises resolve but promise1 resolves faster. Therefore the promise is resolved with the value of promise1, which is the string 'Promise-one'.
Example 2:
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => resolve('succes'), 2000);
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => reject('err'), 1000);
});
Promise.race([promise1, promise2])
.then((value) => {
console.log(value);
}).catch((value) => {
console.log('error: ' + value);
});
In this second example the second promise rejects faster than the first promise can resolve. Therefore Promise.race will return a rejected promise with the value of 'err' which was the value that Promise2 rejected with.
The key point to understand is that Promice.race takes an iterable of Promises and returns a Promise based on the first resolved or rejected promise in that iterable (with the corresponding resolve() or reject() values).
Let's take an sample workaround of Promise.race like below.
const race = (promises) => {
return new Promise((resolve, reject) => {
return promises.forEach(f => f.then(resolve).catch(reject));
})
};
You can see race function executes all promises, but whomever finishes first will resolve/reject with wrapper Promise.

Understanding promise.race() usage

As far as I know, there are two options about promise:
promise.all()
promise.race()
Ok, I know what promise.all() does. It runs promises in parallel, and .then gives you the values if both resolved successfully. Here is an example:
Promise.all([
$.ajax({ url: 'test1.php' }),
$.ajax({ url: 'test2.php' })
])
.then(([res1, res2]) => {
// Both requests resolved
})
.catch(error => {
// Something went wrong
});
But I don't understand what does promise.race() is supposed to do exactly? In other word, what's the difference with not using it? Assume this:
$.ajax({
url: 'test1.php',
async: true,
success: function (data) {
// This request resolved
}
});
$.ajax({
url: 'test2.php',
async: true,
success: function (data) {
// This request resolved
}
});
See? I haven't used promise.race() and it behaves like promise.race(). Anyway, is there any simple and clean example to show me when exactly should I use promise.race() ?
As you see, the race() will return the promise instance which is firstly resolved or rejected:
var p1 = new Promise(function(resolve, reject) {
setTimeout(resolve, 500, 'one');
});
var p2 = new Promise(function(resolve, reject) {
setTimeout(resolve, 100, 'two');
});
Promise.race([p1, p2]).then(function(value) {
console.log(value); // "two"
// Both resolve, but p2 is faster
});
For a scenes to be used, maybe you want to limit the cost time of a request :
var p = Promise.race([
fetch('/resource-that-may-take-a-while'),
new Promise(function (resolve, reject) {
setTimeout(() => reject(new Error('request timeout')), 5000)
})
])
p.then(response => console.log(response))
p.catch(error => console.log(error))
With the race() you just need to get the returned promise, you needn't care about which one of the promises in the race([]) firstly returned,
However, without the race, just like your example, you need to care about which one will firstly returned, and called the callback in the both success callback.
I've used it for request batching. We had to batch tens of thousands of records into batches for a long running execution. We could do it in parallel, but didn't want the number of pending requests to get out of hand.
Race lets us keep a fixed number of parallel promises running and add one to replace whenever one completes
const _ = require('lodash')
async function batchRequests(options) {
let query = { offset: 0, limit: options.limit };
do {
batch = await model.findAll(query);
query.offset += options.limit;
if (batch.length) {
const promise = doLongRequestForBatch(batch).then(() => {
// Once complete, pop this promise from our array
// so that we know we can add another batch in its place
_.remove(promises, p => p === promise);
});
promises.push(promise);
// Once we hit our concurrency limit, wait for at least one promise to
// resolve before continuing to batch off requests
if (promises.length >= options.concurrentBatches) {
await Promise.race(promises);
}
}
} while (batch.length);
// Wait for remaining batches to finish
return Promise.all(promises);
}
batchRequests({ limit: 100, concurrentBatches: 5 });
It's a piece to build a timeout system, where:
the request/computation may be canceled by another channel
it will still be used later, but we need an interaction now.
For an example of the second, one might show a spinner "instantly" while still defaulting to show real content if it comes in fast enough. Try running the below a few times - note at least some console message comes "instantly". This might normally be attached to perform operations on a UI.
The key to note is - the result of Promise.race is much less important than the side effects (though, this then is a code smell).
// 300 ms _feels_ "instant", and flickers are bad
function getUserInfo(user) {
return new Promise((resolve, reject) => {
// had it at 1500 to be more true-to-life, but 900 is better for testing
setTimeout(() => resolve("user data!"), Math.floor(900*Math.random()));
});
}
function showUserInfo(user) {
return getUserInfo().then(info => {
console.log("user info:", info);
return true;
});
}
function showSpinner() {
console.log("please wait...")
}
function timeout(delay, result) {
return new Promise(resolve => {
setTimeout(() => resolve(result), delay);
});
}
Promise.race([showUserInfo(), timeout(300)]).then(displayed => {
if (!displayed) showSpinner();
});
Inspiration credit to a comment by captainkovalsky.
An example of the first:
function timeout(delay) {
let cancel;
const wait = new Promise(resolve => {
const timer = setTimeout(() => resolve(false), delay);
cancel = () => {
clearTimeout(timer);
resolve(true);
};
});
wait.cancel = cancel;
return wait;
}
function doWork() {
const workFactor = Math.floor(600*Math.random());
const work = timeout(workFactor);
const result = work.then(canceled => {
if (canceled)
console.log('Work canceled');
else
console.log('Work done in', workFactor, 'ms');
return !canceled;
});
result.cancel = work.cancel;
return result;
}
function attemptWork() {
const work = doWork();
return Promise.race([work, timeout(300)])
.then(done => {
if (!done)
work.cancel();
return (done ? 'Work complete!' : 'I gave up');
});
}
attemptWork().then(console.log);
You can see from this one that the timeout's console.log is never executed when the timeout hits first. It should fail/succeed about half/half, for testing convenience.
Here's an easy example to understand the use of promise.race():
Imagine you need to fetch some data from a server and if the data takes too long to load (say 15 seconds) you want to show an error.
You would call promise.race() with two promises, the first being your ajax request and the second being a simple setTimeout(() => resolve("ERROR"), 15000)
Summary:
Promise.race is a JS built in function that accepts an iterable of Promises (e.g. Array) as an argument. This function then asynchronously returns a Promise as soon as one in of the Promises passed in the iterable is either resolved or rejected.
Example 1:
var promise1 = new Promise((resolve, reject) => {
setTimeout(() => resolve('Promise-one'), 500);
});
var promise2 = new Promise((resolve, reject) => {
setTimeout(() => resolve('Promise-two'), 100);
});
Promise.race([promise1, promise2]).then((value) => {
console.log(value);
// Both resolve, but promise2 is faster than promise 1
});
In this example first an array of Promises is passed in Promise.race. Both of the promises resolve but promise1 resolves faster. Therefore the promise is resolved with the value of promise1, which is the string 'Promise-one'.
Example 2:
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => resolve('succes'), 2000);
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => reject('err'), 1000);
});
Promise.race([promise1, promise2])
.then((value) => {
console.log(value);
}).catch((value) => {
console.log('error: ' + value);
});
In this second example the second promise rejects faster than the first promise can resolve. Therefore Promise.race will return a rejected promise with the value of 'err' which was the value that Promise2 rejected with.
The key point to understand is that Promice.race takes an iterable of Promises and returns a Promise based on the first resolved or rejected promise in that iterable (with the corresponding resolve() or reject() values).
Let's take an sample workaround of Promise.race like below.
const race = (promises) => {
return new Promise((resolve, reject) => {
return promises.forEach(f => f.then(resolve).catch(reject));
})
};
You can see race function executes all promises, but whomever finishes first will resolve/reject with wrapper Promise.

Categories

Resources