How can i synchronize these 3 promise-based functions? - javascript

How can i synchronize these 3 promise returning functions (For example in other function)? I want to get following output -> Start -> (2secs)..2..(3secs)..3..(4secs)..4 -> End. I've tryed Generators, but my output wasn't like that (Probably i did something wrong)
function resolveAfter2Seconds() {
new Promise(resolve => {
setTimeout(() => {
resolve('resolved 2');
console.log('2')
}, 2000);
});
}
function resolveAfter3Seconds() {
new Promise(resolve => {
setTimeout(() => {
resolve('resolved 2');
console.log('3')
}, 3000);
});
}
function resolveAfter4Seconds() {
new Promise(resolve => {
setTimeout(() => {
resolve('resolved 2');
console.log('4')
}, 4000);
});
}

First, change the functions to return their promises. For example:
function resolveAfter2Seconds() {
return new Promise(resolve => { // <------ added return statement
setTimeout(() => {
resolve('resolved 2');
console.log('2')
}, 2000);
});
}
Then either chain the promises together
resolveAfter2Seconds()
.then(() => resolveAfter3Seconds())
.then(() => resolveAfter4Seconds());
Or use async/await syntax:
async function exampleFunction() {
await resolveAfter2Seconds();
await resolveAfter3Seconds();
await resolveAfter4Seconds();
}

You might want to try chaining to get the sequential output:
resolveAfter2Seconds()
.then(() => resolveAfter3Seconds())
.then(() => resolveAfter4Seconds())
PS. Don't forget to make those functions return promises.

Related

Proper use of async JS to ensure function calls wait for previous functions to complete (resolve?)

Trying to learn proper async/await JavaScript to run functions in sequence when an early function in the sequence would be delayed (using setTimeout to simulate). I'm not getting the expected results (still getting "first", "second", "this should run first?" - see code).
What am I missing? Do I have the wrong idea about this?
Thanks in advance!
const zeroFunction = () => {
setTimeout(() => {
return new Promise((resolve) => {
console.log("This should run first?");
resolve();
});
}, 2000)}
const firstFunction = () => {
return new Promise((resolve) => {
console.log("first");
resolve();
})
}
const secondFunction = () => {
return new Promise((resolve) => {
console.log("second");
resolve();
})
}
async function fnAsync() {
await zeroFunction();
await firstFunction();
secondFunction();
}
fnAsync();
zeroFunction is currently returning undefined implicitly, not a Promise. Inverse the wrapping of the setTimeout and Promise constructor and it should work as expected.
const zeroFunction = () => {
return new Promise((resolve) => {
setTimeout(() => {
console.log("This should run first?")
resolve()
}, 2000)
})
}
const firstFunction = () => {
return new Promise((resolve) => {
console.log("first")
resolve()
})
}
const secondFunction = () => {
return new Promise((resolve) => {
console.log("second")
resolve()
})
}
async function fnAsync() {
await zeroFunction()
await firstFunction()
secondFunction()
}
fnAsync()

Traditional way of doing asnyc method in javascript

I was searching online on how we create the traditional way of doing async function in Javascript but it wasn't available. I have implemented a promise function in my program, however the software that I am using (tableu) to create all custom styling does not support ES5-ES8 and async functions, as this will throw an error, so I was wondering if this is possible.
function promise() {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(), 500);
})
}
async function result() {
await promise();
}
result().then(render => {
customStyle()
});
All of my code shown is working fine. I'm wondering how can I convert this to the old way of doing async functions. Is this possible or is it only available in ES8?
Callbacks are the non-Promise or async/await way of doing this, and are basically how those things work under the hood.
Here's a simple example by modifying your snippet:
function promise(callback) {
setTimeout(() => callback(), 500);
}
function result() {
promise(callback);
}
function callback() {
customStyle();
};
Instead of result being an async function that you can await elsewhere in your code, it could also take a callback argument, like promise, that you would pass it when it's invoked. The implementation of that callback function would be like the then of an actual Promise.
Now you can see why the Promise API and async/await were such nice improvements to the spec.
To use promises the tradicional way, you have to replace the await and use .then(()=> ...). I'll try to show a snippet here to help you to understood.
The code that you have shown does not need the async or await, it goes well like that
function promise() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('resolved')
resolve()
}, 500);
})
}
promise().then(render => {
customStyle()
});
Here i'll show you a code that have a good use of it and then I'll convert it:
function callSomeService() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('service whas called')
resolve({ idOfSomething: 1 })
}, 2000);
})
}
function callAnotherServiceUsingTheDataOfThePreviousCall(data) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('service whas called with', data)
resolve(['potato 1', 'potato 2', 'potato 3'])
}, 2000);
})
}
async function result() {
const serviceResponse = await callSomeService();
const arrayOfPotatos = await callAnotherServiceUsingTheDataOfThePreviousCall(serviceResponse);
return arrayOfPotatos.map((potato, index) => `${index} - ${potato}`)
}
result().then(arrayOfPotatos => {
arrayOfPotatos.forEach(potato => console.log(potato))
});
Now I'll convert it to not use async or await, but still using promises.
function callSomeService() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('service whas called')
resolve({ idOfSomething: 1 })
}, 2000)
})
}
function callAnotherServiceUsingTheDataOfThePreviousCall(data) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('service whas called with', data)
resolve(['potato 1', 'potato 2', 'potato 3'])
}, 2000)
})
}
function result() {
return callSomeService().then(serviceResponse => {
return callAnotherServiceUsingTheDataOfThePreviousCall(
serviceResponse
).then(arrayOfPotatos => {
return arrayOfPotatos.map((potato, index) => `${index} - ${potato}`)
})
})
}
result().then(arrayOfPotatos => {
arrayOfPotatos.forEach(potato => console.log(potato))
})
Those two last codes does the same thing, but the second use async and await and the third does not. Async and await are just a syntax sugar to use promises.
I expect that will help you.

How to make an async then?

Basically I am trying to play around to understand more of async/await and promise in JS. I'm trying to make Hello comes in between finished! and third finish!!. So the best guess is, making second then asnyc and await for console.log('Hello'). I've tried both ways below but both are not working as expected.
Approach A
let promise = new Promise((res,rej)=>{
res();
});
promise.then(() => {
console.log('finished!')
}).then(() => {
setTimeout(async function(){
await console.log("Hello"); }, 3000); //async/await at setTimeout level
}).then(() => {
console.log('third finish!!')
})
Approach B:
let promise = new Promise((res,rej)=>{
res();
});
promise.then(() => {
console.log('finished!')
}).then(async () => { //async/await at thenlevel
await setTimeout(function(){
console.log("Hello"); }, 3000);
}).then(() => {
console.log('third finish!!')
})
You need the second section to be a Promise, and return it from the .then so that it's properly chained between the first and the third. setTimeout doesn't return a Promise, you have to explicitly construct a Promise instead:
let promise = new Promise((res,rej)=>{
res();
});
promise.then(() => {
console.log('finished!')
}).then(() => {
return new Promise(resolve => {
setTimeout(function(){
console.log("Hello");
resolve();
}, 1000);
});
}).then(() => {
console.log('third finish!!')
})
Or, using await, use await new Promise followed by the same Promise construction and the setTimeout:
let promise = new Promise((res, rej) => {
res();
});
promise.then(() => {
console.log('finished!')
}).then(async() => {
await new Promise(resolve => {
setTimeout(function() {
console.log("Hello");
resolve();
}, 1000);
});
}).then(() => {
console.log('third finish!!')
})
Another approach is to write an asynchronous setAsyncTimeout function (this hasn't been thoroughly tested, may need tweaks):
async function setAsyncTimeout(callback, interval) {
return new Promise( (resolve, reject) => {
setTimeout(() => {
try {
let inner = callback()
if (inner && inner.then) {
inner.then(resolve, reject)
} else {
resolve(inner)
}
} catch(e) {
reject(e)
}
}, interval)
})
}
Testing via your example:
let promise = new Promise((res,rej)=>{
res();
});
promise.then(() => {
console.log('finished!')
}).then( setAsyncTimeout(function(){
console.log("Hello"); }, 3000);
}).then(() => {
console.log('third finish!!')
})
Testing via your example (with another promise):
let promise = new Promise((res,rej)=>{
res();
});
promise.then(() => {
console.log('finished!')
}).then(async () => { //async/await at thenlevel
await setAsyncTimeout(function(){
console.log("Hello");
return setAsyncTimeout(() => console.log("world"), 3000)
}, 3000);
}).then(() => {
console.log('third finish!!')
})
Cleaner example:
let promise = new Promise((res,rej)=>{
res();
});
promise.then(() => {
console.log('finished!')
}).then(() => {
return setAsyncTimeout(() => { console.log("Hello"); }, 3000)
}).then(() => {
console.log('third finish!!')
})

Understanding Promise and Await

I am just trying to understand how Promises and Async-Await work.
I want this to resolve by logging 1, 2, 3 in that order. Currently it logs 1, 3, 2.
I know the Promise doesn't really make sense here but in my program it has other uses so that needs to stay. The route from Caller function to Test also needs to stay (If need be you can change these but just know that they are there for a reason)
My question is how do I wait for the Caller function to resolve?
Here is my code:
function Test() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('2');
resolve();
}, 2000);
})
}
function Caller() {
Test();
}
console.log('1');
Caller();
console.log('3');
I have tried what I understand, which is to make the Caller() function await the Test Promise, but that of course makes the Caller() function async and therefore we still get 1, 3, 2
async function Caller() {
await Test();
}
Is there maybe some way to use await without making the function async?
You can only await a function that returns a promise (well, not quite true, if it doesn't return a promise it creates a promise that resolves instantly)
You can only await when you are inside an asynchronous function
function test() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('2');
resolve();
}, 2000);
})
}
async function caller() {
console.log('1');
await test();
console.log('3 (this is blocked awaiting the promise');
}
caller()
console.log("This is not blocked because caller is async");
This is a very straightforward, simple way of doing what you ask.
The await keyword can only be used inside functions
defined with async.
function test(ms) {
return new Promise((resolve, reject) => setTimeout(resolve, ms))
}
async function caller() {
console.log(1, ' - caller() started');
await test(2000).then(() => {
console.log(2, ' - test() resolved')
});
console.log(3, ' - delayed until "test()" has resolved');
return 4;
}
// wait for "caller()" to resolve
caller().then((result) => {
console.log(result, " - caller() finished")
});
console.log(5);
Here's a good article by Google which expands on the subject:
Async functions - making promises friendly.
Cite source.
here is how you could use functions like this:
function sleep(ms) {
return new Promise(r => {
setTimeout(() => r(), ms);
});
}
(async () => {
console.log(1);
await sleep(1000); // 1s
console.log(2);
await sleep(2000) // 2s
console.log(3)
})();
The previous answers are all correct but I just feel like this answer makes more sense. It is more accurate to the original question's code:
function Test() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('2');
resolve();
}, 2000);
})
}
function Caller() {
return Test();
}
(async() => {
console.log('1');
await Caller();
console.log('3');
})();

Refactoring Promise to Async/wait. Why I got undefiened?

I have the code on Promise:
function one() {
return new Promise((rs,er)=>{
console.log('start');
new Promise((rr,err)=>{setTimeout(()=>{console.log('after 3 sec');rr()},3000)})
.then( sd => {
console.log('endLong');
rs();
})
});
}
one().then(_ => one()).then(_ => one());
And as a result I get syncronized code.
But when I refactoring it to async/wait
async function one() {
console.log('start');
await longtime();
console.log('endLong');
}
async function longtime() {setTimeout(()=>{console.log('after 3 sec');},3000);}
one().then(_ => one()).then(_ => one())
then I got:
start
endLong
start
endLong
start
endLong
PromiseĀ {<resolved>: undefined}
after 3 sec
after 3 sec
after 3 sec
What's wrong?
You need longtime to return a promise. A setTimeout alone does not mean anything to promise-based async/await:
async function one() {
console.log('start');
await longtime();
console.log('endLong');
}
const longtime = () => new Promise((resolve, reject) => {
setTimeout(() => {
console.log('after 0.5 sec');
resolve();
}, 500);
});
one()
.then(_ => one())
.then(_ => one())
setTimeout does not return a promise. An async function should return a promise that's resolved with the value.
function longtime() {
return new Promise(resolve => {
setTimeout(() => {
console.log('after 3 sec');
resolve();
}, 3000);
});

Categories