How can I set async for setTimeout in JavaScript - javascript

const delayTime = (time) =>
setTimeout(() => {
console.log("run after:", time);
}, time);
const runTime = async () => {
await delayTime(1000);
await delayTime(900);
};
runTime();
And actual result is:
run after: 900
run after: 1000
And expected result I want:
run after: 1000
run after: 900

Async/await works with promises under the hood, so you need to return a promise from your delayTime function.
The Promise constructor accepts an executor function that is run synchronously (ie. immediately) with two callback functions as arguments: one to resolve the promise and another to reject the promise.
setTimeout and setInterval were added to JavaScript years before promises were widely understood, and are therefore not immediately compatible with promises: you need to "promisify" them.
To promisify a setTimeout expression you wrap it in a promise executor function and call the resolve callback function from inside the setTimeout callback .
const delayTime = (time) =>
new Promise((resolve) => setTimeout(() => {
console.log("run after:", time);
resolve();
}, time));
const runTime = async () => {
await delayTime(1000);
await delayTime(900);
};
runTime();

It's more logical to have timeout function separately, and call action (log) in caller function:
// Timeout function
const timeout = ms => new Promise(resolve => setTimeout(resolve, ms));
// Caller function
const test = async () => {
// Do all stuff here
console.log(`starting...`);
await timeout(3000);
console.log(`3 sec passed...`);
await timeout(5000);
console.log(`8 sec passed, finishing.`);
}
// Run test
test();

The reason your you see 900 hundred printed earlier is that the time out set for setTimeout is not constant. 900 milliseconds pass faster than 1000 millisecs, so hence 900 is printed earlier.
I have changed the method to pass the time-out delay with the respective message. Here is the implementation:
const delayTime = ( delay, displayMessage) =>
setTimeout(() => {
console.log("run after:", displayMessage );
}, delay);
const runTime = async () => {
await delayTime(1000, '1000');
await delayTime(1000, '900');
};
runTime();

Related

Why does this sequence of await function calls run in the wrong order?

I want to output some text after 2 seconds first, after output some "alert()" second and at the end output some "console.log" by using only async/await. Please help me how to write such a sequence?
Why the code below does not work
async function qaz()
{
let res1 = await setTimeout(function(){
console.log("show me first");
}, 2000);
let res2 = await alert('show me second');
let res3 = await console.log('show me at the end');
return [res1,res2,res3];
}
The setTimeout is part of the JavaScript asynchronous methods (methods that are starting to execute and their result will return sometime in the future to a component called the callback queue, later to be executed)
What you probably want to do is to wrap the setTimeout function within a Promise and await it and then execute the rest of the synchronous code.
const longTask = () => new Promise(resolve => {
setTimeout(function(){
console.log("show me first");
resolve();
}, 2000);
});
async function qaz()
{
await longTask();
alert('show me second');
console.log('show me at the end');
}
qaz();
I suggest to read more about the event loop model here
Neither the setTimeout, the alert, or the console.log return promises, and that's a problem because await only works with promises.
You can still use async/await, however. Create a delay function that returns a promise you can await for the first part, and then after that resolves do your alerts and your logging.
function delay(n) {
return new Promise(res => {
setTimeout(() => res(), n);
});
}
async function qaz() {
await delay(2000);
console.log('Show me first');
alert('Show me second');
console.log('Show me at the end');
}
qaz();

Promise.all vs [await x, await y] - Is it really the same? [duplicate]

This question already has answers here:
Any difference between await Promise.all() and multiple await?
(6 answers)
Closed 1 year ago.
This is a basic question, but i couldn't find the answer to it anywhere.
We have two approaches:
// consider someFunction1() and someFunction2() as functions that returns Promises
Approach #1:
return [await someFunction1(), await someFunction2()]
Approach #2:
return await Promise.all([someFunction1(), someFunction2()])
My Team Leader said that both approaches ended up in the same solution (both functions executting in parallel). But, from my knowledge, the first approach would await someFunction1() to resolve and then would execute someFunction2.
So that's the question, is it really the same, or are there any performance improvements on second approach? Proofs are very welcome!
No, you should not accept that:
return [await someFunction1(), await someFunction2()];
Is the same as:
return await Promise.all([someFunction1(), someFunction2()]);
I should also note that await in the above return await is not needed. Check out this blog post to learn more.
They are different!
The first approach (sequential)
Let's determine the difference by inspecting how each of the two alternatives works.
[await someFunction1(), await someFunction2()];
Here, in an async context, we create an array literal. Note that someFunction1 is called (a function which probably returns a new promise each time it gets called).
So, when you call someFunction1, a new promise is returned, which then "locks" the async context because the preceding await.
In a nutshell, the await someFunction1() "blocks" the array initialization until the returned promise gets settled (by getting resolved or rejected).
The same process is repeated to someFunction2.
Note that, in this first approach, the two promises are awaited in sequence. There is, therefore, no similarity with the approach that uses Promise.all. Let's see why.
The second approach (non-sequential)
Promise.all([someFunction1(), someFunction2()])
When you apply Promise.all, it expects an iterable of promises. It waits for all the promises you give to resolve before returns a new array of resolved values, but don't wait each promise resolve until waiting another one. In essence, it awaits all the promises at the same time, so it is a kind of "non-sequential". As JavaScript is single-threaded, you cannot tell this "parallel", but is very similar in the behavior point of view.
So, when you pass this array:
[someFunction1(), someFunction2()]
You are actually passing an array of promises (which are returned from the functions). Something like:
[Promise<...>, Promise<...>]
Note that the promises are being created outside Promise.all.
So you are, in fact, passing an array of promises to Promise.all. When both of them gets resolved, the Promise.all returns the array of resolved values. I won't explain in all details how Promise.all works, for that, I suggest you checking out the documentation.
You can replicate this "non-sequential" approach by creating the promises before using the await. Like so:
const promise1 = someFunction1();
const promise2 = someFunction2();
return [await promise1, await promise2];
While promise1 is being waited, promise2 is already running (as it was created before the first await), so the behavior is similar to Promise.all's.
My Team Leader said that both approaches ended up in the same solution (both functions executting in parallel).
That is incorrect.
But, from my knowledge, the first approach would await someFunction1() to resolve and then would execute someFunction2.
That is correct.
Here is a demonstration
Approach 1:
const delay = (ms, value) =>
new Promise(resolve => setTimeout(resolve, ms, value));
async function Approach1() {
return [await someFunction1(), await someFunction2()];
}
async function someFunction1() {
const result = await delay(800, "hello");
console.log(result);
return result;
}
async function someFunction2() {
const result = await delay(400, "world");
console.log(result);
return result;
}
async function main() {
const start = new Date();
const result = await Approach1();
const totalTime = new Date() - start;
console.log(`result: ${result}
total time: ${totalTime}`);
}
main();
Result is:
hello
world
result: hello,world
total time: 1205
Which means that someFunction1 runs to completion first and then someFunction2 is executed. It is sequential
Approach 2:
const delay = (ms, value) =>
new Promise(resolve => setTimeout(resolve, ms, value));
async function Approach2() {
return await Promise.all([someFunction1(), someFunction2()]);
}
async function someFunction1() {
const result = await delay(800, "hello");
console.log(result);
return result;
}
async function someFunction2() {
const result = await delay(400, "world");
console.log(result);
return result;
}
async function main() {
const start = new Date();
const result = await Approach2();
const totalTime = new Date() - start;
console.log(`result: ${result}
total time: ${totalTime}`);
}
main();
Result is:
world
hello
result: hello,world
total time: 803
Which means that someFunction2 finishes before someFunction1. The two are parallel.
Easy to see the difference
function createTimer(ms, id) {
console.log(`id: ${id} started ${new Date()}`);
return new Promise((res, rej) => {
setTimeout( () => {
console.log(`id: ${id} finished ${new Date()}`);
res(id);
}, ms );
});
}
(async function() {
var result1 = [await createTimer(5000, '1'), await createTimer(5000, '2')];
var result2 = await Promise.all([createTimer(5000, '3'), createTimer(5000, '4')]);
console.log(result1);
console.log(result2);
})();
The first one starts 1 and when 1 finishes it starts 2.
The second one starts 3 and 4 at almost the very same moment.
If you start with a function which simulates doing some work which outputs at stages of that work but takes some time. eg
function someFunction1(){
return new Promise(resolve => {
let i = 0;
const intervalId = setInterval(() => {
i++;
console.log("someFunction1", i);
if(i == 5){
clearInterval(intervalId)
resolve(1);
}
}, 1000);
});
}
And then you duplicate that with a second, similar, method. You plug your 2 methods in and you see that the one using Promise.all does it in parallel but the one using 2 await calls does it in series.
Parallel
function someFunction1(){
return new Promise(resolve => {
let i = 0;
const intervalId = setInterval(() => {
i++;
console.log("someFunction1", i);
if(i == 5){
clearInterval(intervalId)
resolve(1);
}
}, 1000);
});
}
function someFunction2(){
return new Promise(resolve => {
let i = 0;
const intervalId = setInterval(() => {
i++;
console.log("someFunction2", i);
if(i == 5){
clearInterval(intervalId)
resolve(2);
}
}, 1000);
});
}
(async function(){
const result = await Promise.all([someFunction1(),someFunction2()]);
console.log("result",result);
})();
Series
function someFunction1(){
return new Promise(resolve => {
let i = 0;
const intervalId = setInterval(() => {
i++;
console.log("someFunction1", i);
if(i == 5){
clearInterval(intervalId)
resolve(1);
}
}, 1000);
});
}
function someFunction2(){
return new Promise(resolve => {
let i = 0;
const intervalId = setInterval(() => {
i++;
console.log("someFunction2", i);
if(i == 5){
clearInterval(intervalId)
resolve(2);
}
}, 1000);
});
}
(async function(){
const result = [await someFunction1(),await someFunction2()];
console.log("result",result);
})();
Both give the exact same result but getting there is very different.
MDN documentation for Promise.all() states that
This method can be useful for aggregating the results of multiple promises. It is typically used when there are multiple related asynchronous tasks that the overall code relies on to work successfully — all of whom we want to fulfill before the code execution continues.
While it isn't explicit, you can await Promise.all to track multiple promises. Only when all promises are resolved will the code execution continue.
The other approach you mention of capturing separate asynchronous tasks in an array is not the same due to how await operates.
An await splits execution flow, allowing the caller of the async function to resume execution. After the await defers the continuation of the async function, execution of subsequent statements ensues. If this await is the last expression executed by its function, execution continues by returning to the function's caller a pending Promise for completion of the await's function and resuming execution of that caller.
So, each await will pause execution before resuming. No need for a demonstration.

Is there anyway to rewrite this function with async in the first function. Instead of a "new Promise"?

This is the function that is working.
const delayedColorChange = (color, delay) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
document.body.style.backgroundColor = color;
resolve();
}, delay);
});
};
const rainbow = async() => {
await delayedColorChange('red', 1000);
await delayedColorChange('orange', 1000);
await delayedColorChange('yellow', 1000);
await delayedColorChange('green', 1000);
await delayedColorChange('blue', 1000);
await delayedColorChange('indigo', 1000);
await delayedColorChange('violet', 1000);
await delayedColorChange('pink', 1000);
return 'ALL DONE';
};
rainbow().then(console.log);
Trying to make delayedColorChange into an async function.
const delayedColorChange = async (color, delay) => {
setTimeout(() => {
document.body.style.backgroundColor = color;
}, delay);
};
In this code the backgrounColor on the website is going straight to pink.
why is that?
Basically, is there any way to make delayedColorChange into an async function?
To my understanding, async functions returns a promise, so, why not just use an async function, instead of having to create a "new Promise" in a regular function?.
Is this even possible?
Sorry for the loaded post.
Is there anyway to rewrite this function with async in the first function. Instead of a “new Promise”?
No, there is not. Not if you want the function to return a promise that is tied to when the timer fires.
async functions are very useful when you are calling functions that already return promises and you want to use await to help with the control flow on those existing promise-returning functions.
But, when you have a function like setTimeout() that does not use a promise at all and you want to "promisify" it so you can use promise-based control flow, you will have to use some means of making a new promise and wrapping the existing callback in that new promise. For setTimeout(), the code you show is the standard way to do that.
It is a bit more common and generically useful to promisify just the timer because then you can use this lots of places and it is generally recommended when promisifying things to promisify at the lowest level (because it's more extensible and you build all your logic on top of promise-based control flow):
// promise-based timer
function delay(t, v) {
return new Promise(resolve => {
setTimeout(resolve, t, v);
});
}
const delayedColorChange = (color, t) => {
return delay(t).then(() => {
document.body.style.backgroundColor = color;
});
};
In this code the backgroundColor on the website is going straight to pink. why is that?
Your snippet in your question does not go straight to pink (if you just hit "run code snippet" right in your question) so if your real web page is going straight to pink, then something must be different in that implementation from this one.
I would write a promise-based generic sleep function -
const sleep = ms =>
new Promise(r => setTimeout(r, ms))
async delayedColorChange (color, delay)
{ await sleep(delay)
document.body.style.backgroundColor = color;
}
Here's how I might write rainbow -
const sleep = ms =>
new Promise(r => setTimeout(r, ms))
const setBackgroundColor = (e, color) =>
e.style.backgroundColor = color
async function rainbow (e, colors, i = 0)
{ while (true)
{ setBackgroundColor(e, colors[i])
i = (i + 1) % colors.length
await sleep(600)
}
}
const colors =
["red", "orange", "yellow", "green", "blue", "indigo", "violet"]
rainbow(document.body, colors)
body {
transition: background-color .6s;
}
First, it's worth noting that setTimeout does not guarantee that your callback will be executed in exactly delay milliseconds; it adds your callback function to the JS event queue after delay milliseconds. If there are long-running functions in line in front of this callback then your callback gets delayed longer. I don't know if that is relevant to what you're doing here, but it's good to keep in mind.
This also explains why your last code snippet goes directly to pink. You are adding a series of functions to the event queue all 1 second from now and they all execute extremely quickly. The last one leaves the background pink, so that's all you're able to observe on the page.
Your first function can be a little more concise, which should help readability in a year when you revisit this, but there isn't a JS function (that I'm aware of) that performs asynchronous sleeping.
const delayedColorChange = async(color, delay) => {
await new Promise(resolve => setTimeout(resolve, delay));
document.body.style.backgroundColor = color;
};
const rainbow = async() => {
await delayedColorChange('red', 1000);
await delayedColorChange('orange', 1000);
await delayedColorChange('yellow', 1000);
await delayedColorChange('green', 1000);
await delayedColorChange('blue', 1000);
await delayedColorChange('indigo', 1000);
await delayedColorChange('violet', 1000);
await delayedColorChange('pink', 1000);
return 'ALL DONE';
};
rainbow().then(console.log);
Adding the await to delayedColorChange is what introduces the delay in the promise being returned. Without an await, your async function executes synchronously and returns an already resolved promise.

How to measure the execution time of a promise?

I'm trying to write a function that measures the execution time of another function:
export class Profiler {
public measureSyncFunc(fn: () => any): Promise<number> {
return new Promise<number>((resolve, reject) => {
let elapsed = 0;
let intervalId = window.setInterval(() => {
elapsed += 1; // this is never called
}, 1);
this.execFunc(fn)
.then((result: any) => {
window.clearInterval(intervalId);
resolve(elapsed);
});
});
}
private execFunc(fn: () => any): Promise<any> {
return new Promise<any>((resolve, reject) => {
resolve(fn());
});
}
}
Then I use it like that:
let array = generateRandomArray(100000);
instance.measureSyncFunc(bubbleSort(array))
.then((elapsed: number) => {
console.log(`end session: ${elapsed} seconds`);
resolve();
});
The bubbleSort function is synchronous and it takes several seconds to complete.
See code here:
The result in the console is "end session: 0 seconds" because the interval callback is never called.
Do you know how I can make it called ?
Thank you very much guys !
If the functions you want to measure will always be synchronous there's really no need to involve promises.
Since the function you want to test takes parameters you it's best to to wrap it in an arrow function in order to be able to call it with another context and not have to manage it's parameters yourself.
Something simple like this will do just fine.
function measure(fn: () => void): number {
let start = performance.now();
fn();
return performance.now() - start;
}
function longRunningFunction(n: number) {
for (let i = 0; i < n; i++) {
console.log(i);
}
}
let duration = measure(() => {
longRunningFunction(100);
});
console.log(`took ${duration} ms`);
If you want to measure the time it takes an async function (if it returns a promise) to resolve you can easily change the code to something like this:
function measurePromise(fn: () => Promise<any>): Promise<number> {
let onPromiseDone = () => performance.now() - start;
let start = performance.now();
return fn().then(onPromiseDone, onPromiseDone);
}
function longPromise(delay: number) {
return new Promise<string>((resolve) => {
setTimeout(() => {
resolve('Done');
}, delay);
});
}
measurePromise(() => longPromise(300))
.then((duration) => {
console.log(`promise took ${duration} ms`);
});
Note: This solution uses the ES6 Promise, if you are using something else you might have to adapt it but the logic should be the same.
You can see both examples working in the playground here.
Don't use setInterval to count milliseconds (It's inaccurate, lags, drifts and has a minimum interval of about 4ms). Just get two timestamps before and after the execution.
function measureAsyncFunc(fn: () => Promise<any>): Promise<number> {
const start = Date.now();
return fn.catch(() => {}).then(() => {
const end = Date.now();
const elapsed = end-start;
return elapsed;
});
}
For higher accuracy, replace Date.now by performance.now.
Have a look at timeFnPromise and the related test cases.
target function is wrapped and executed when the wrapped function is called
appends fulfillment / rejection handler to the underlying Promise that returns the target functions return value as "ret" and the elapsed time as "elapsedTime"
supports arguments by passing them through to the target function
Samples Usage:
const wrappedFn = timeFnPromise(aFunctionThatReturnsAPromise)
wrappedFn()
.then((values)=>{
const {ret, elapsedTime} = values
console.log(`ret:[${ret}] elapsedTime:[${elapsedTime}]`)
})
Also available via NPM module jschest.
Here's a simple wrapper function I wrote. It returns a Promise (via the async keyword), and so you can just call it with your promise. I added the time value as a property to the response. If you cannot have that value in the response, then you would need to remove it afterwards.
const stopwatchWrapper = async (promise) => {
const startTime = Date.now()
const resp = await promise
resp.executionTime = Date.now() - startTime
return resp
}
const axiosPromise = stopwatchWrapper(axios(reqSelected))
const response = await axiosPromise
console.log(response.executionTime)
It would be good to clarify that the proposed approaches by toskv only work with the resolution of a single promise. If we want to use Promise.all() the time result it returns is wrong.
Here is an example with the code that toskv developed, but using Promise.all()
Measure with Promise.all()
If someone needs to measure the time it takes to execute each of the promises executed with a Promise.all() the approach that can be followed is to make use of the interceptors and do the time measurements there

How do you wrap setTimeout in a promise [duplicate]

This question already has answers here:
What is the JavaScript version of sleep()?
(91 answers)
Closed 1 year ago.
I am trying to run a test suite for an object that returns a promise. I want to chain several actions together with short timeouts between them. I thought that a "then" call which returned a promise would wait for the promise to be fulfilled before firing the next chained then call.
I created a function
function promiseTimeout (time) {
return new Promise(function(resolve,reject){
setTimeout(function(){resolve(time);},time);
});
};
to try and wrap setTimeout in a Promise.
Then in my test suite, I am calling something like this ...
it('should restore state when browser back button is used',function(done){
r.domOK().then(function(){
xh.fire('akc-route-change','/user/4/profile/new');
}).then(promiseTimeout(2000)).then(function(t){
xu.fire('akc-route-change','/user/6');
}).then(promiseTimeout(10)).then(function(t){
expect(xu.params[0]).to.equal(6);
history.back();
}).then(promiseTimeout(10)).then(function(){
expect(xu.params[0]).to.equal(4);
done();
});
});
I can put a breakpoint on the first xh.fire call and a second one on the xu.fire call and would have expected a two second gap when a continues from the first breakpoint to the second.
Instead it reaches the second breakpoint immediately, and the value of t at that point is undefined.
What am I doing wrong?
TL;DR - you've wrapped setTimeout in a promise properly, the issue is you are using it improperly
.then(promiseTimeout(2000)).then
will not do what you expect. The "signature" for .then is then(functionResolved, functionRejected)
A promise’s then method accepts two arguments:
promise.then(onFulfilled, onRejected)
Both onFulfilled and onRejected are optional arguments:
If onFulfilled is not a function, it must be ignored.
If onRejected is not a function, it must be ignored.
source: https://promisesaplus.com/#point-21
You are not passing a function to then
Consider the way you are doing it:
Promise.resolve('hello')
.then(promiseTimeout(2000))
.then(console.log.bind(console))
vs how it should be done:
Promise.resolve('hello').then(function() {
return promiseTimeout(2000)
}).then(console.log.bind(console))
The first outputs 'hello' immediately
The second outputs 2000 after 2 seconds
Therefore, you should be doing:
it('should restore state when browser back button is used', function(done) {
r.domOK().then(function() {
xh.fire('akc-route-change', '/user/4/profile/new');
}).then(function() {
return promiseTimeout(2000);
}).then(function(t) {
xu.fire('akc-route-change', '/user/6');
}).then(function() {
return promiseTimeout(10);
}).then(function(t) {
expect(xu.params[0]).to.equal(6);
history.back();
}).then(function() {
return promiseTimeout(10);
}).then(function() {
expect(xu.params[0]).to.equal(4);
done();
});
});
Alternatively:
it('should restore state when browser back button is used', function(done) {
r.domOK().then(function() {
xh.fire('akc-route-change', '/user/4/profile/new');
}).then(promiseTimeout.bind(null, 2000)
).then(function(t) {
xu.fire('akc-route-change', '/user/6');
}).then(promiseTimeout.bind(null, 10)
).then(function(t) {
expect(xu.params[0]).to.equal(6);
history.back();
}).then(promiseTimeout.bind(null, 10)
).then(function() {
expect(xu.params[0]).to.equal(4);
done();
});
});
EDIT: March 2019
Over the years, things have changed a lot - arrow notation makes this even easier
Firstly, I would define promiseTimeout differently
const promiseTimeout = time => () => new Promise(resolve => setTimeout(resolve, time, time));
The above returns a function that can be called to create a "promise delay" and resolves to the time (length of delay). Thinking about this, I can't see why that would be very useful, rather I'd:
const promiseTimeout = time => result => new Promise(resolve => setTimeout(resolve, time, result));
The above would resolve to the result of the previous promise (far more useful)
But it's a function that returns a function, so the rest of the ORIGINAL code could be left unchanged. The thing about the original code, however, is that no values are needed to be passed down the .then chain, so, even simpler
const promiseTimeout = time => () => new Promise(resolve => setTimeout(resolve, time));
and the original code in the question's it block can now be used unchanged
it('should restore state when browser back button is used',function(done){
r.domOK().then(function(){
xh.fire('akc-route-change','/user/4/profile/new');
}).then(promiseTimeout(2000)).then(function(){
xu.fire('akc-route-change','/user/6');
}).then(promiseTimeout(10)).then(function(){
expect(xu.params[0]).to.equal(6);
history.back();
}).then(promiseTimeout(10)).then(function(){
expect(xu.params[0]).to.equal(4);
done();
});
});
To make a timeout which works as you want, write a function which takes a delay, and returns a function suitable for passing to then.
function timeout(ms) {
return () => new Promise(resolve => setTimeout(resolve, ms));
}
Use it like this:
Promise.resolve() . then(timeout(1000)) . then(() => console.log("got here"););
However, it is likely that you will want to access the resolved value of the promise leading into the timeout. In that case, arrange for the function created by timeout() to pass through the value:
function timeout(ms) {
return value => new Promise(resolve => setTimeout(() => resolve(value), ms));
}
Use it like this:
Promise.resolve(42) . then(timeout(1000)) . then(value => console.log(value));
This has already been answered above, but I feel this could be done easily with:
const setTimeoutPromise = ms => new Promise(resolve => setTimeout(resolve, ms))
setTimeoutProise function accept wait time in ms and passes it down to the setTimeout function. Once the wait time is over, the resolve method passed down to the promise is executed.
Which could be used like this:
setTimeoutPromise(3000).then(doSomething)
await new Promise((resolve, reject)=>{
// wait for 50 ms.
setTimeout(function(){resolve()}, 50);
});
console.log("This will appear after waiting for 50 ms");
This can be used in an async function and the execution will wait till given interval.
Another approach for adding delays to Promises without having to predefine or import a helper function (that I personally like best) is to extend the property of the Promise constructor:
Promise.prototype.delay = function (ms) {
return new Promise(resolve => {
window.setTimeout(this.then.bind(this, resolve), ms);
});
}
I'm leaving out the reject callback since this is meant to always resolve.
DEMO
Promise.prototype.delay = function(ms) {
console.log(`[log] Fetching data in ${ms / 1000} second(s)...`);
return new Promise(resolve => {
window.setTimeout(this.then.bind(this, resolve), ms);
});
}
document.getElementById('fetch').onclick = function() {
const duration = 1000 * document.querySelector('#duration[type="number"]').value;
// Promise.resolve() returns a Promise
// and this simply simulates some long-running background processes
// so we can add some delays on it
Promise
.resolve('Some data from server.')
.delay(duration)
.then(console.log);
}
<div>
<input id="duration" type="number" value="3" />
<button id="fetch">Fetch data from server</button>
</div>
Or if you need it to also be .catch()-able, here is when you need the second argument (reject). Note that the catch() handling will also occur after the delay:
Promise.prototype.delay = function(ms) {
console.log(`[log] Fetching data in ${ms / 1000} second(s)...`);
return new Promise((resolve, reject) => {
window.setTimeout(() => {
this.then(resolve).catch(reject);
}, ms);
});
}
document.getElementById('fetch').onclick = function() {
const duration = 1000 * document.querySelector('#duration[type="number"]').value;
Promise
.reject('Some data from server.')
.delay(duration)
.then(console.log)
.catch(console.log); // Promise rejection or failures will always end up here
}
<div>
<input id="duration" type="number" value="3" />
<button id="fetch">Fetch data from server</button>
</div>

Categories

Resources