Javascript Promise chaining not working as expected - javascript

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.

Related

javascript promises: returning promises with another return inside results in same behavior as using with out 2nd return

I was trying out Promises and have the 2 functions below. I was calling test1() and then using then() to call test2(). The behavior worked as expected with test1 completed logged after 3 seconds and then immediately logging test2 completed. My question is that when I add another return before the setTimeout, it still works the same. Why would that be the case?
function test1() {
return new Promise((resolve, reject) {
setTimeout(() => {
console.log("test1 completed");
resolve(true);
}, 3000);
});
// return new Promise((resolve, reject) {
// return setTimeout(() => {
// console.log("test1 completed");
// resolve(true);
// }, 3000);
// });
}
function test2() {
console.log("test2 completed");
}

A .then doesn't run after the promise gets resolved on AWS Lambda

Code:
var promiseResolve, promiseReject;
function iterateRules(rules, params, i = 0) {
CWevents.putRule(rules[i], function(err, data) { // This is an async function with a callback
if (err) console.log(err); promiseReject(err)
responses++
params['Lambda_invoke']['SourceArns'].push(data.RuleArn)
if(responses == rules.length){ promiseResolve("Success"); console.log("Resolved")}
// After two responses are confirmed, this if does run and I get the "Resolved"
})
i++
if(i < rules.length){
setTimeout( function(){
iterateRules(params['CW_rules']['Rules'], params, i)
}, 50)
}
}
new Promise((resolve, reject) => {
resolve()
// This part is added solely for the code to make sense, it's taken out of a
// bigger script and lots of unnecessary data is removed
})
.then((Item) => {
return new Promise((resolve, reject) => {
promiseReject = reject;
promiseResolve = resolve;
iterateRules(params['CW_rules']['Rules'], params)
})
}) .then((res) => {
console.log("This ran")
})
The iterateRules function is supposed to run an asynchronous function multiple times, and resolve the Promise it's called in when the last response is acquired. The if(responses == rules.length) does run as expected and logs the "Resolved" in the console. Everything is successful, no errors.
Beneath is the context of this code, the iterateRules function is executed, but the .then that comes after, isn't. If I put a resolve() inside the promise directly, it does execute. What might be wrong with this script? I tried running a simple version of it that looks like this separately:
var res, rej;
function dude(){
res()
}
new Promise((resolve, reject) => {
res = resolve;
dude()
}).then((dude) => {
console.log("resolved")
})
And it does in fact work, so I'm very confused. What might cause the problem?
I would make iterateRules() return a promise (since it is asynchronous). I would also promisify the CWevents.putRule() function so you can accomplish some code like the below:
function iterateRules(rules, params) {
return Promise.all(rules.map(rule => {
return CWevents.putRule(rule)
})).then((data) => {
params['Lambda_invoke']['SourceArns'].push(data.RuleArn)
})
}
Then your handler for iterateRules would become:
iterateRules(rules,params).then(()=>{
// Do something...
})

Async/Await code not being executes after await

I have been going over async/await. I trying few simple examples but unable to understand flow of async and await . In below code
function wait(ms) {
return new Promise(r => setTimeout(function() {
console.log('Hello');
}, ms));
}
async function GetUser() {
await wait(5000);
console.log('world');
}
GetUser();
Why is the message "world" not logged? Only "Hello" prints.
You should call the resolver.
function wait(ms) {
return new Promise(r => setTimeout(function(){console.log('Hello'); r();},
// ^^^ this
ms));
}
Reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
You need to resolve it. So call r()
function wait(ms) {
return new Promise(r => setTimeout(function() {
console.log('Hello');
r()
}, ms));
}
async function GetUser() {
await wait(3000)
console.log('world');
}
GetUser()
Here wait() method returns a Promise, the function of await keyword is to stop code execution until the returned Promise by wait() is resolved.
So the code snippet in question, without using async/await will be as below. Note that the resolve function is not yet invoked here. Hence, once the snippet is executed only Hello will get printed in the console.
// First code snippet
function wait(ms) {
return new Promise(r => setTimeout(function () {
console.log('Hello');
}, ms));
}
function GetUser() {
return wait(1000)
.then(() => {
console.log("World")
})
.catch((err) => {
console.log(err);
})
}
GetUser()
Code snippet when r() is invoked. Here, once the snippet is executed Hello and World both are printed in the console.
// Second code snippet
function wait(ms) {
return new Promise(r => setTimeout(function () {
console.log('Hello');
r();
}, ms));
}
function GetUser() {
return wait(1000)
.then(() => {
console.log("World")
})
.catch((err) => {
console.log(err);
})
}
GetUser()
The reason why the second code snippet works, has to do with how Promise is implemented in JS.
Handler function/functions attached to a promise with the help of .then() are invoked only when the promise is resolved.
Code snippet when resolve method is not invoked inside the executor function i.e, when the Promise is not resolved. Here, only code inside setTimeout is invoked and not the handlers.
function wait(ms) {
return new Promise(r => setTimeout(function () {
console.log('Hello');
}, ms));
}
const promiseReturnedByWaitMethod = wait(2000);
// Multiple handlers can be added to a promise reference, which are executed when the asynchronous operation is completed.
// adding first handler
promiseReturnedByWaitMethod.then(() => {
console.log("First handler!!")
});
// adding second handler
promiseReturnedByWaitMethod.then(() => {
console.log("Second handler!!")
});
Code snippet when resolve method is invoked inside the executor function i.e, when the Promise is resolved.
function wait(ms) {
return new Promise(r => setTimeout(function () {
console.log('Hello');
r();
}, ms));
}
const promiseReturnedByWaitMethod = wait(2000);
// Multiple handlers can be added to a promise reference, which are executed when the asynchronous operation is completed.
// adding first handler
promiseReturnedByWaitMethod.then(() => {
console.log("First handler!!")
});
// adding second handler
promiseReturnedByWaitMethod.then(() => {
console.log("Second handler!!")
});

returning a promise from the then of another promise

i am a little new at this. Please help
I am trying to return a promise from a function. This seems to work well until I try to return the promise in the then of an existing promise.
I am trying to do this in a FireFox extension. The code below is written for node.js as I thought it might give more explanation. I cannot figure out how to make it work.
function topLevel calls function level2. level2 waits for a promise to resolve and then returns a promise to level1. level1 logs in its .then.
level2 calls level3 after its internal promise is resolved and returns a new promise
In the example all promises resolve immediately. The example is paired down to the essentials
function topLevel() {
level2()
.then(() => {
console.log("topLevel resolved")
})
}
let testError=true;
function level2() {
if(testError) {
new Promise((resolve, reject) => {
resolve("Level 2");
})
.then(() => {
return (level3());
})
}
else {
return (level3());
}
}
function level3(){
return (new Promise((resolve, reject) => {
resolve("Level 3");
}));
}
topLevel();
there is a variable "testError" which changes the behavior of level 2. When set to "true" level2 waits for a promise and returns a promise from level3 in that promises then statement. level3 is run but the console.log in level1 never executes and an error results. When set to false everything works (promise from level3 is returned directly rather than in .then. The error is Cannot read property 'then' of undefined in toplevel .then.
The firefox webextension code from a background script is below
browser.browserAction.onClicked.addListener(topLevel);
function topLevel() {
level2()
.then(() => {
console.log("topLevel resolved")
})
}
function level2() {
new Promise((resolve, reject) => {
resolve("Level 2");
})
.then(() => {
return (level3());
})
}
function level3(){
return (new Promise((resolve, reject) => {
resolve("Level 3");
}));
}
It causes a warning in level2 between the .then and return statements that
"level2 is undefined". and again the log in level one never happens.
Any way to make this work?? I need to rely on this pattern
level2 does not return anything when testError is true.
The thenable (the function given to then) is a function. The return statement inside the thenable only concern the thenable itself (just like any function).
Change to
function level2() {
if (testError) {
return new Promise((resolve, reject) => {
resolve("Level 2");
}).then(() => {
return level3();
});
}
return level3();
}
I think it's as simple as adding a return before new Promise... in line 12. Revised code:
function topLevel() {
level2()
.then(() => {
console.log("topLevel resolved")
})
}
let testError = true;
function level2() {
if(testError) {
// Added "return" here
return new Promise((resolve, reject) => {
resolve("Level 2");
})
.then(() => {
return (level3());
})
}
else {
return (level3());
}
}
function level3() {
return (new Promise((resolve, reject) => {
resolve("Level 3");
}));
}
You need to return the new Promise you create in the level2 function.

Is this possible to limit javascript function executing time?

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");
});

Categories

Resources