function first(){
console.log("1")
}
function second(){
new Promise ((resolve,reject)=>{
setTimeout(function(){
console.log("2")
resolve();
} ,0);
})
}
function third(){
console.log("3")
}
async function run(){
first();
await second();
third();
}
run();
Need to make the function call sync to get final output as 1,2,3 i tried creating the promise and use async await but that didnt help any other way
Pack the setTimeout into a promise and resolve in setTimeout,
Use async await for that promise in order for that to run consecutively
function first() {
console.log("1")
}
function second() {
return new Promise(res => {
setTimeout(function() {
console.log("2");
res()
}, 0)
})
}
function third() {
console.log("3")
}
async function run() {
first();
await second()
third();
}
run();
Related
I have simplified this problem. I have 3 functions which I want to run with a 2 second delay between each. The following code is working:
$.when(one()).done(function () {
$.when(delay(2000)).done(function () {
$.when(two()).done(function () {
$.when(delay(2000)).done(function () {
$.when(three()).done(function () {
console.log('finished');
});
});
});
});
});
function delay(ms) {
var waitForDelay = new $.Deferred();
setTimeout(function () {
waitForDelay.resolve().promise();
}, ms);
return waitForDelay.promise();
}
function one() {
console.log('one');
return new $.Deferred().resolve().promise();
}
function two() {
console.log('two');
return new $.Deferred().resolve().promise();
}
function three() {
console.log('three');
return new $.Deferred().resolve().promise();
}
However when I try to refactor it, it no longer waits for the delayed amounts of time:
one().done(delay(2000)).done(two).done(delay(2000)).done(three).done(function () {
console.log('finished');
});
How can I refactor to chain these promises rather than nesting them? I want to use jQuery for older browser compatibility.
My advice would be to not use jQuery's weird promise-like data structures at all.
Have your functions return an actual Promise (either explicitly or by making them async functions) and await each step in the chain.
const delay = (ms) => new Promise((res) => setTimeout(res, ms));
// an async function implicitly returns a promise
const one = async () => {
console.log("one");
}
// or you can return one manually
const two = () => {
console.log("two");
return Promise.resolve();
}
const three = async () => {
console.log("three");
}
// await each step in an async function (an async IIFE in this case)
(async () => {
await one();
await delay(2000);
await two();
await delay(2000);
await three();
console.log("finished");
})();
You can also use .then() if you prefer that style
// Convenience function so you don't repeat yourself
const waitTwoSeconds = () => delay(2000);
one()
.then(waitTwoSeconds)
.then(two)
.then(waitTwoSeconds)
.then(three)
.then(() => {
console.log("finished");
});
If you must use jQuery, it doesn't really look much different
function delay(ms) {
var d = $.Deferred();
setTimeout(d.resolve, ms);
return d.promise();
}
function one() {
console.log("one");
return $.Deferred().resolve().promise();
}
function two() {
console.log("two");
return $.Deferred().resolve().promise();
}
function three() {
console.log("three");
return $.Deferred().resolve().promise();
}
function waitTwoSeconds() {
return delay(2000);
}
one()
.then(waitTwoSeconds)
.then(two)
.then(waitTwoSeconds)
.then(three)
.then(function() {
console.log("finished");
});
<!-- Note jQuery 1.8 was the first to have chainable deferreds -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
I've used .then() instead of .done() because the latter does not chain and using $.when() is unnecessary when .then() is available.
Taking inspiration from Phil's answer, here is a solution compatible with older browsers.
First, change the delay() function to return a function:
function delay(ms) {
return function() {
var waitForDelay = new $.Deferred();
setTimeout(function () {
waitForDelay.resolve().promise();
}, ms);
return waitForDelay.promise();
}
}
All other functions stay the same as in the question.
Finally replace the .done()s with .then()s to make them chain:
one().then(delay(2000)).then(two).then(delay(2000)).then(three).then(function () {
console.log('finished');
});
async function doThings() {
async function timer () {
setTimeout(() => {
console.log('timer!')
}), 1000
}
async function printer () {
console.log('printer!')
}
await timer()
await printer()
}
doThings()
I thought making the function async made it return a promise and await made it wait. Why does printer() finish first?
Your timer function doesn't work because setTimeout does not return a promise that could be awaited. You will need to promisify it manually:
// set a default of 1500
function timeout(ms=1500) {
return new Promise(resolve => setTimeout(resolve, ms));
};
async function printer() {
console.log('printer!');
};
async function doThings() {
await timeout(1000); // time in ms
await printer();
};
doThings();
The word “async” before a function means one simple thing: a function always returns a Promise. Other values are wrapped in a resolved Promise automatically.
Now when we use don't return Promise from async function, then javascript interpreter automatically returns resolved Promise, so that is the reason await on timer function got the resolved Promise and interpreter went ahead with the execution, but there is a setTimeout still going on. So we have to return a Promise from timer function, and resolve it inside setTimeout function like below.
async function doThings() {
async function timer() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(`timer!`);
resolve();
}, 1000)
});
}
async function printer() {
console.log('printer!')
}
await timer()
await printer()
}
doThings()
All I can see is timer () and printer () functions are async functions but there is no await used in them, and this makes the async keyword unfunctional.
I've been using async with NodeJS, but I'm trying to understand the basic of promises in JavaScript and I'm having issues with it.
I created the code below for testing.
function first() {
// Simulate a code delay
return new Promise(function(resolve) {
setTimeout(function() {
console.log(1);
}, 500);
});
}
function second() {
console.log(2);
}
first().then(second());
It should print '1' first, but it is printing '2' in the console first. Why is it happening?
Thanks
Two things:
first().then(second()) invokes second() immediately and passes its return value as the argument to then. You want to pass in the function itself, not its return value:
first().then(second); // no parens on second
And you're never resolving the first promise:
return new Promise(function(resolve) {
setTimeout(function() {
console.log(1);
resolve(); // <-- without this the promise is never resolved
}, 500);
}
);
With those issues addressed it works as you'd intended:
function first() {
// Simulate a code delay
return new Promise(function(resolve) {
setTimeout(function() {
console.log(1);
resolve(); // <-- without this the promise is never resolved
}, 500);
});
}
function second() {
console.log(2);
}
first().then(second);
There are a 2 problems in your code :
Your function first() returns a promise, but it isn't a promise in itself, so you cannot use the .then attribute on it.
You're not resolving anything in your 1st promise, you're just console.logging something, which is not something you can "wait" for.
What you're looking for is more something like this :
let first = new Promise((resolve) => {
setTimeout( function() {
console.log("1");
resolve(true); //you return your response, for example a boolean
}, 500)
})
function second(){
console.log("2");
}
first.then(response => {
//this is usually where you do something with the response
second();
});
Use Async Await
(as ray write) In new Promise() You must return resolve() or reject()
You can also use await:
function first() {
return new Promise(res => {
console.log(1);
return setTimeout(res, 500);
})
}
function second() {
console.log(2);
}
(async () => {
await first();
second();
})();
I have little doubt, I have let say 5 or more js functions each calls C# functions Via Ajax calls doing various task like(fetching data from the database, validating it, calculations, saving it back to The database etc).
I am calling the function using Nested jQuery $.when(function1()).then(function2()) and so on. I want function one to fully complete before two and two before the third one and so one.... there are some dependency between these functions...
My Code example Like: (My Approach)
$(document).ready(function () {
$.when(one()).then(
$.when(two()).then(
$.when(three()).done(alert('three done')).then(
$.when(four()).then(
five()
).done(alert('All Finished Up'))
)
)
)
});
function one() //eg List 1000 records from Db
function two() //Update Some
function three() //validate Changes
function four() //save Changes
function five() // Some Other Task then
Now my question is simple I know rather than calling sequentially like
$(document).ready(function(){
one();
two();
three();
four();
five();
});
I used above nesting pattern (My Approach)... Is that good approach coding-wise and performance wise? Is there any more efficient approach than this?
Alternatively, you can run all of those calls in parallel to get a faster return
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function one(mode) {
await sleep(1000);
console.log(`${mode} : one() finished`);
}
async function two(mode) {
await sleep(3000);
console.log(`${mode} : two() finished`);
}
async function three(mode) {
await sleep(3000);
console.log(`${mode} : three() finished`);
}
async function four(mode) {
await sleep(4000);
console.log(`${mode} : four() finished`);
}
async function five(mode) {
await sleep(5000);
console.log(`${mode} : five() finished`);
}
async function runInSerial() {
await one('serial');
await two('serial');
await three('serial');
await four('serial');
await five('serial');
}
async function runInParallel() {
await Promise.all([
one('parallel'),
two('parallel'),
three('parallel'),
four('parallel'),
five('parallel'),
]);
}
$(document).ready(function () {
runInSerial().then(() => console.log('serial : all done!'));
runInParallel().then(() => console.log('parallel : all done!'));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
There is: if you want to only support browsers that support ES6, you can simply use the async/await syntax, as the jQuery Promises return a native Promise object anyway:
// Dummy async operation
function sleep(t) {
return new Promise(resolve => setTimeout(resolve, t));
}
$(document).ready(function() {
run().then(() => console.log('all done'));
});
// Run all your async functions sequentially
async function run() {
await one();
console.log('one done');
await two();
console.log('two done');
}
async function one() {
return sleep(500);
}
async function two() {
return sleep(500);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
function one(){
console.log(1);
}
function two(callback){
setTimeout(()=>{
console.log(2);
},2000);
callback();
}
two(one);
While I am running this code, 1 is displaying first and then 2 because 2 is taking 2 second time to display. Suppose if there is an api instead of console.log(2) in function two which is taking 2 second to respond, so How I can call function one after completion of function two using callback(); which I can do in this case if I use callback() inside setTimeout function but what if there is an api where I am not using setTimeout and it's taking 2-3 second?
Even if there is an api call which takes time to resolve, you can still use a callback at the same way you just did with the setTimeout example.
Alternatively, use a Promise:
function two(callback) {
new Promise(res => {
setTimeout(() => {
res();
}, 2000);
}).then(callback)
}
or using async/await syntax:
async function two(callback) {
await new Promise(res => {
setTimeout(() => {
res();
}, 2000);
})
callback();
}
you can use sync function like this
function two() {//this function takes 2 seconds
return new Promise(resolve => {
setTimeout(() => {
resolve('resolved');
}, 2000);
});
}
function one(){
console.log("one");
}
async function asyncCall() {
console.log('calling');
const result = await two();
one()
// expected output: 'resolved'
}
asyncCall();
here is reference link
You can use Promises:
function one(){
console.log(1);
}
function two(){
return new Promise((resolve, reject) => {
setTimeout(()=>{
console.log(2);
resolve()
},2000);
})
}
two().then(() => one())
Put callback(); inside setTimeout:
function one(){
console.log(1);
}
function two(callback){
setTimeout(()=>{
console.log(2);
callback();
},2000);
}
two(one);