Doesn't Closure on Promise Work With Asynchronously Affected Value? - javascript

On the second then method there is a closed value(string), and I'm running setTimeout to change it after 1 second.
Also I'm returnin new Promise to resolved with setTimeout after 2 second to the value I'm changing with the previous setTimeout.
But after it resolved next then method logs out the value that is not affected by previous setTimeout.
Shouldn't I get 'foobarbaz' from the last then method's log.
Thanks in advance...
var p1 = new Promise((resolve, reject) => {
resolve('foo');
});
p1.then(function(string) {
return new Promise(res => {
setTimeout(() => {
string += 'bar';
res(string);
}, 2000);
});
})
.then(function(string) {
setTimeout(function() {
string += 'baz';
console.log(string);
}, 1000);
return new Promise(resolve => setTimeout(resolve, 2000, string));
})
.then(function(string) {
console.log(string);
});

The issue is:
return new Promise(resolve => setTimeout(resolve, 2000, string));
This results in setTimeout getting an argument of what is currently in the string variable at the moment that line is run - although string gets reassigned in the upper setTimeout, that setTimeout hasn't run yet, so string remains foobar.
Similarly:
let a = 'foo';
setTimeout(console.log, 200, a);
a = 'bar';
results in foo being logged, not bar.
If you pass a function that, when called, references what string is bound to when said function is called, results will be as expected:
return new Promise(resolve => setTimeout(() => {
resolve(string);
}, 2000));
var p1 = new Promise((resolve, reject) => {
resolve('foo');
});
p1.then(function(string) {
return new Promise(res => {
setTimeout(() => {
string += 'bar';
res(string);
}, 2000);
});
})
.then(function(string) {
setTimeout(function() {
string += 'baz';
console.log(string);
}, 1000);
return new Promise(resolve => setTimeout(() => {
resolve(string);
}, 2000));
})
.then(function(string) {
console.log(string);
});

Related

How does Javascript Promise work with setTimeOut [duplicate]

This question already has answers here:
Why does the `then()` handler of a promise execute immediately?
(3 answers)
Closed last month.
I apologize if this is a basic question. I am really puzzled by how Promise works in Javascript.
I have the following piece of code:
function wait(ms) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("Done waiting");
resolve(ms);
}, ms);
});
}
let a = true;
let p = new Promise(async (resolve, reject) => {
await wait(3000);
console.log("Inside Promise");
if (a) {
resolve("Success");
} else {
reject("Failure");
}
});
const func = async () => {
let output = await p;
console.log(output);
};
func().then(console.log("abc"));
This is the printout:
abc
Done waiting
Inside Promise
Success
I cannot, for the life of me, figure out why abc is printed first. Shouldn't it wait for func() to finish executing? I expected abc to be printed last. Can anyone walk me through the steps of execution? Thanks in advance. I would really appreciate it.
What you've provided to Promise.then is not a callback and it is evaluated immediately at runtime. You need to move the console.log into the body of the function instead:
func().then(() => console.log("abc"));
See working example below:
function wait(ms) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("Done waiting");
resolve(ms);
}, ms);
});
}
let a = true;
let p = new Promise(async (resolve, reject) => {
await wait(3000);
console.log("Inside Promise");
if (a) {
resolve("Success");
} else {
reject("Failure");
}
});
const func = async () => {
let output = await p;
console.log(output);
};
func().then(() => console.log("abc"));

Javascript class chaning with Promise [duplicate]

I am trying to make a method sleep(delay) in method chaining. For this I am using setTimeout with Promise. This will require any method following the sleep to be inside the then.
Right now I am calling the function like
lazyMan("John", console.log).eat("banana").sleep(5).then(d => {d.eat("apple");});.
Here is my code
function lazyMan(name, logFn) {
logFn(name);
return {
eat: function(val) {
console.log(val);
return this;
},
sleep: function(timer) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(`Sleeping for ${timer} seconds`);
resolve(this);
}, timer * 1000);
}).then(d => this);
}
};
}
lazyMan("John", console.log)
.eat("banana")
.sleep(5)
.then(d => {
d.eat("apple");
});
Is there a way I can modify my function to call it like lazyMan("John", console.log).eat("banana").sleep(5).eat("apple") and get the output in same order
I have gone through Add a sleep method in a object method chain(JS)
You can keep a promise for your "task queue", so anything that needs to be done, will be added onto there via .then(). This provides a fluent API for scheduling stuff.
function lazyMan(name, logFn) {
logFn(name);
let taskQueue = Promise.resolve();
const addTask = f => {
taskQueue = taskQueue.then(f);
}
return {
eat: function(val) {
addTask(() => console.log(`Eating [${val}]`));
return this;
},
sleep: function(timer) {
addTask(() => new Promise((resolve, reject) => {
console.log(`Start sleeping for ${timer} seconds`);
setTimeout(() => {
console.log(`End sleeping for ${timer} seconds`);
resolve();
}, timer * 1000);
}))
return this;
}
};
}
lazyMan("John", console.log)
.eat("banana")
.sleep(5)
.eat("apple");
Note that this change means that every action is technically asynchronous. However, that's at least uniform, so it's less of a chance of a surprise when keeping it in mind.

Why doesn't the code after "await" in this JavaScript ES6 example get run?

I have the following snippet:
let zxcv = () => new Promise((resolve, reject) => {
setTimeout(() => {
console.log(4)
}, 1000)
})
async function jk(){
await zxcv()
console.log(6)
}
jk()
When I run this snippet, it waits for a second, then logs "4", then ends. "6" never gets logged.
Why?
You never resolved your promise in zxcv:
let zxcv = () => new Promise((resolve, reject) => {
setTimeout(() => {
console.log(4)
resolve()
}, 1000)
})
Otherwise the promise will hang indefinitely!

2 functions on Promise chaining are being called asynchronously

I am learning javascript Promise. I have created 2 independent functions and am chaining them in a promise function. However the second function gets called first even though it is in the second then() block.
Code is below.
const one = document.getElementById('one');
function clkw(a){
setTimeout(() => {
one.innerHTML = a;
return 2*a;
}, 2000);
}
function clkw2(b){
setTimeout(() => {
one.innerHTML += ' '+b;
}, 2000);
}
function trypromise(){
const np = new Promise(resolve => {
setTimeout(() => {
resolve(10)
}, 2000);
});
np
.then(function(data){
return clkw(data);
})
.then(function(bata){
clkw2(bata);
});
}
If you want to chain and still be able to execute async code in the then continuation, you have to return a promise that resolves only when the result is ready.
In your snippet you don't actually return any values (or promises) from chained thens that can be used down the pipeline. Because of that, the result is automatically converted to a resolved promise that doesn't have any value.
const one = document.getElementById('one');
function clkw(a){
return new Promise(res => {
setTimeout(() => {
one.innerHTML = a;
res(2*a);
}, 2000);
});
}
function clkw2(b){
return new Promise(res => {
setTimeout(() => {
one.innerHTML += ' '+b;
res();
}, 2000);
});
}
function trypromise(){
const np = new Promise(resolve => {
setTimeout(() => {
resolve(10)
}, 2000);
});
np
.then(function(data){
return clkw(data);
})
.then(function(bata){
clkw2(bata);
});
}
trypromise();
<div id='one'></div>
However the second function gets called first even though it is in the second then() block.
Everything works as expected in the code you provided. How did you observe the strange behavior?
const one = document.getElementById('one');
function clkw(a) {
console.log("clkw");
setTimeout(() => {
one.innerHTML = a;
return 2 * a;
}, 2000);
}
function clkw2(b) {
console.log("clkw2");
setTimeout(() => {
one.innerHTML += ' ' + b;
}, 2000);
}
function trypromise() {
const np = new Promise(resolve => {
setTimeout(() => {
resolve(10)
}, 2000);
});
np
.then(function(data) {
return clkw(data);
})
.then(function(bata) {
clkw2(bata);
});
}
trypromise()
<div id="one"></div>

How to execute functions sequentially using Node Js Promise?

I'm new to Node js Promise I'm not sure whether I'm using the Promise correctly or not so here is my code.
function print(){
first('first')
.then(second('second'))
.then(third('third'));
}
function first(a){
return new Promise((resolve, reject) => {
var res1 = function (){
resolve(a);
}
});
console.log(a);
}
function second(b){
return new Promise((resolve, reject) => {
var res1 = function (){
resolve(b);
}
});
setTimeout(() => {
console.log(b);
}, 2000);
}
function third(c){
return new Promise((resolve, reject) => {
var res1 = function (){
resolve(c);
}
});
console.log(c);
}
My desired output is
first
second
third
Instead what I get is
first
third
//after two seconds
second
I'm missing something but I can't figure it out please explain me
To get the expected behaviour, you need to resolve inside of the timeout (next to the console log). You also cannot pass arguments into promise chain functions since they need to accept the promise from the previous thennable.
A working snippet is below:
print();
function print(){
first('first')
.then(second)
.then(third);
}
function first(a){
return new Promise((resolve, reject) => {
console.log(a);
resolve(a);
});
}
function second(b){
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("second");
resolve(b);
}, 2000);
});
}
function third(c){
return new Promise((resolve, reject) => {
console.log("third");
resolve(c)
});
}

Categories