Promise catch behavior - javascript

it seems the following works without throwing an error:
var p = new Promise (function (resolve, reject) {
window.setTimeout(function() {
reject('ko');
}, 1000);
});
p.then(function (value) { console.log(value); })
.catch(function () { console.log('catched'); });
// → 'catched'
But this throws an error:
var p = new Promise (function (resolve, reject) {
window.setTimeout(function() {
p.catch(function () { console.log('catched'); });
reject('ko');
}, 1000);
});
p.then(function (value) { console.log(value); });
// → 'catched'
// Uncaught (in promise) ko
Any wild guesses to why ?

The .catch must be directly chained after .then. Even if you write it this way, it will still report uncaught:
var p = new Promise(function(resolve, reject) {
window.setTimeout(function() {
//p.catch(function () { console.log('catched'); });
console.log(p)
reject('ko');
}, 1000);
});
p.then(function(value) {
console.log(value);
});
p.catch(function() {
console.log('catched');
});
The reason for this is that if you don't chain it like that, the .catch function doesn't receive the return value that gets generated when you call .then

Related

named promise chainy for normal promises that handle events

I am trying to create a named promise chain. I am not sure of how to achieve this. The goal is following:
function multiplepromises() {
var prom = function (resolve, reject) {
var lifecycleeventone = new someEvent();
var lifecycleeventtwo = new someEvent();
var lifecycleeventthree = new someEvent();
var lifecycleeventfour = new someEvent();
var lifecycleeventfive = new someEvent();
lifecycleeventone.on(function () {
try {
resolve("eventone")
} catch {
reject("eventone")
}
})
lifecycleeventtwo.on(function () {
try {
resolve("eventtwo")
} catch {
reject("eventtwo")
}
})
lifecycleeventthree.on(function () {
try {
resolve("eventthree")
} catch {
reject("eventthree")
}
})
lifecycleeventfour.on(function () {
try {
resolve("eventfour")
} catch {
reject("eventfour")
}
})
lifecycleeventfive.on(function () {
try {
resolve("eventfive")
} catch {
reject("eventfive")
}
})
maineventlikefinallySOcalledalways.on(function(){
try {
resolve("maineventlikefinallySOcalledalways")
} catch {
reject("maineventlikefinallySOcalledalways")
}
})
}
return prom
}
multiplepromises()
.onlifecycleeventoneAsProm((result)=> result) //eventone promise resolve
.onlifecycleeventoneerrorAsProm((error)=> error) //eventone
.onlifecycleeventtwoAsProm((result)=> result) //eventtwo promise resolve
.onlifecycleeventtwoerrorAsProm((error)=> error) //eventtwo
.onlifecycleeventthreeAsProm((result)=> result) //eventthree promise resolve
.onlifecycleeventthreeerrorAsProm((error)=> error) //eventthree
.onlifecycleeventfourAsProm((result)=> result) //eventfour promise resolve
.onlifecycleeventfourerrorAsProm((error)=> error) //eventfour
.onlifecycleeventfiveAsProm((result)=> result) // eventfive promise resolve
.onlifecycleeventfiveerrorAsProm((error)=> error) //eventfive
.then((result)=> result) // maineventlikefinallySOcalledalways promise resolve
.error((error)=> error) // maineventlikefinallySOcalledalways promise reject
multiplepromises()
.onlifecycleeventoneAsProm((result)=> result) //eventone promise resolve
.onlifecycleeventoneerrorAsProm((error)=> error) //eventone
.onlifecycleeventtwoAsProm((result)=> result) //eventtwo promise resolve
.onlifecycleeventtwoerrorAsProm((error)=> error) //eventtwo
.onlifecycleeventthreeAsProm((result)=> console.log("test"))
// lifecycleeventthree promise reject stops here and
// doesnt continue to .then/.error since there was no return from this lifecycle event(promise)
I have read this and this doesnt solve the purpose completely.
Handling multiple catches in promise chain and https://javascript.info/promise-chaining
Dont want to use Rx and want to keep to vanilla js
You can‘t achieve something like that with Promises.
Instead you can make a function that returns an object with event registrar functions, which return again the object.
Here is a simple example:
function test() {
return new (function() {
this.eh = {};
this.on = (event, handler) => {
this.eh[event] = handler;
return this;
}
this.call = (event, ...args) => {
if (typeof this.eh[event] === 'function') {
this.eh[event](...args);
}
}
Promise.resolve().then(() => {
// Do your stuff...
// Example:
this.call('msg', 'This is a message.');
setTimeout(() => {
this.call('some-event', 'This is some event data.');
this.call('error', 'This is an error.');
}, 1000);
});
})()
}
test()
.on('msg', (msg) => console.log(`Message: ${msg}`))
.on('some-event', (data) => console.log(`Some event: ${data}`))
.on('error', (err) => console.log(`Error: ${err}`))
I hope that‘s what you were up to.
Edit:
Here's another attempt: https://jsfiddle.net/bg7oyxau/

Then function isn't called after returning a promise

I created a function to check if an element already exist, if not repeat the function until it does:
function waitForElementToDisplay(selector) {
return new Promise(function (resolve, reject) {
if (document.querySelector(selector) != null) {
console.log('Element is displayed now');
resolve();
} else {
setTimeout(function () {
waitForElementToDisplay(selector, 500);
}, 500);
}
})
}
I use this function in the beforeShowPromise function of Shepherd.js. This function let the package wait with going to the next tour step until the promise is resolved. The beforeShowPromise function looks like this:
beforeShowPromise: function () {
return new Promise(async function (resolve) {
const selector = '.exampleTemplates';
await waitForElementToDisplay(selector).then(() => {
console.log('Do something');
}).catch(err => {
console.log(err);
});
})
},
I want to wait until the waitForElementToDisplay function is resolved, so the function of Shepherd can be resolved. However, the .then nor the .catch functions are being called. Can someone explain to me why it isn't working?
The Promise only resolves if the element exists.
If it doesn't, you hit the else branch which calls the function recursively. This creates a new promise, but you never do anything when that resolves. The original promise is left sitting in limbo.
You can resolve the original promise with the new promise:
resolve( waitForElementToDisplay(selector) );
You need to pass along the resolve to the recursive call:
const checkIfElementExists = (resolve, selector) => {
if (document.querySelector(selector) !== null) {
console.log('Element is displayed now');
resolve();
} else {
setTimeout(checkIfElementExists, 500, resolve, selector);
}
};
function waitForElementToDisplay(selector) {
return new Promise(function(resolve) {
checkIfElementExists(resolve, selector);
})
}
Or, encapsulated inside waitForElementToDisplay:
function waitForElementToDisplay(selector) {
return new Promise(function(resolve) {
(function checkIfElementExists() {
if (document.querySelector(selector) !== null) {
console.log('Element is displayed now');
resolve();
} else {
setTimeout(checkIfElementExists, 500);
}
})();
})
}

How to use promise in while(JavaScript/Node.js)?

I'm trying to execute repeatly multiple processes in sequence by using promise and while (JavaScript/Node.js).
However, the promise function is not executed (i.e., all console.log() is never displayed).
Why is the promise function never executed in the while?
Also, how can I display the some console.log() repeatedly in sequence?
var count = 0;
while(count < 5) {
Promise.resolve()
.then(function () {
return new Promise(function(resolve, reject) {
console.log('func1()...');
resolve('OK');
});
})
.then(function(value) {
return new Promise(function(resolve, reject) {
console.log('func2()...');
resolve('OK');
});
})
.then(function (value) {
console.log('func3()...');
count++;
}).catch(function (error) {
console.log(error);
});
}
.then() still remains an asynchronous callback, see the order of messages here:
Promise.resolve().then(()=>console.log("got resolved"));
console.log("got here");
One thing you can do is wrap the code into an async function:
async function test(){
var count = 0;
while(count < 5) {
await Promise.resolve()
.then(function () {
return new Promise(function(resolve, reject) {
console.log('func1()...');
resolve('OK');
});
})
.then(function(value) {
return new Promise(function(resolve, reject) {
console.log('func2()...');
resolve('OK');
});
})
.then(function (value) {
console.log('func3()...');
count++;
}).catch(function (error) {
console.log(error);
});
}
}
test();
What is happening - in Javascript the event loop and source code you write is executed in one thread. It means that if this one thread is blocked by some work, nothing else is executed.
It works quite straightforward - event loop takes one event (code you show) and it processes ALL synchronous part and it pushes any asynchronous things (the promise chain) to event loop to be executed later.
The issue is this:
var count = 0;
while(count < 5) {
Promise.resolve()
.then(
// some promise chain...
}
The while is catched in never ending loop, as all the synchronous part is that it push this Promise chain in event loop and then starting again. The count is never changed in this context.
The best for you is to use async/await which solves exactly what you want without need deeply understand Node.js
The other option is to use recursion
function promiseChain() {
return Promise.resolve()
.then(function () {
return new Promise(function(resolve, reject) {
console.log('func1()...');
resolve('OK');
});
})
.then(function(value) {
return new Promise(function(resolve, reject) {
console.log('func2()...');
resolve('OK');
});
})
.then(function (value) {
console.log('func3()...');
count++;
}).catch(function (error) {
console.log(error);
});
}
recursivelyExecute(promise, count) {
if (count > 5) {
return;
}
count++;
return promise.then(() => recursivelyExecute(promiseChain(), count+1));
}
var count = 0;
while(count < 5) {
Promise.resolve()
.then(function () {
return new Promise(function(resolve, reject) {
console.log('func1()...');
resolve('OK');
});
})
.then(function(value) {
return new Promise(function(resolve, reject) {
console.log('func2()...');
resolve('OK');
});
})
.then(function (value) {
console.log('func3()...');
}).catch(function (error) {
console.log(error);
});
count++;
}
You need to use Promise.all() along with async.eachSeries for looping. For this you need to install async then do the following:
const async = require('async');
var count = [...Array(5).keys()];
async.eachSeries(count, (c, next) => {
Promise.all([
new Promise(function (resolve, reject) {
console.log('func1()...');
resolve('OK');
}),
new Promise(function (resolve, reject) {
console.log('func2()...');
resolve('OK');
})]).then(function (values) {
console.log('func3()...');
next();
});
}, (err) => {
console.log("here we done");
});

Issue with promise: ReferenceError: reject is not defined

I am working with some own built promise examples to understand how this function is working.
That following code produces the error
ReferenceError: reject is not defined
I start this with node Promise.js and use node version 8.11.3
Here is my code, the part which produces the error is commented with "problem
function testPromise () {
//part 1
function checkCountOnServer () {
return new Promise(function (resolve, reject) {
var available = false
if (available) {
resolve('available')
}
else {
reject('not available')
}
})
}
function checkPayment () {
return new Promise(function (resolve, reject) {
var booleanTest = true
if (booleanTest) {
resolve('payment done')
}
else {
reject('no payment received')
}
})
}
var checkCountOnServerVar = checkCountOnServer()
checkCountOnServerVar.then(function (resolve) {
console.log(resolve)
return resolve(checkPayment())
}, function (reason) {
console.log(reason) //works
reject(reason) // problem
}).then(function (value) { console.log(value) },
function (rejected) {
console.log(rejected) //problem
})
}
testPromise()
I actually expect the message 'not available' two times.
Even if I change reject(reason) to reject('test') I get the same error.
Help me please.
checkCountOnServerVar.then(function (resolve) {
The then callback is called with whatever value the promise was resolved to, which is "payment done" in your case,and that is not a function, so you can't call it. To chain a promise from inside a then handler, just return it:
checkCountOnServerVar.then(function (status) {
console.log(status);
return checkPayment();
})
Additionally your error catcher does not make sense at all,
function (reason) {
console.log(reason) //works
reject(reason) // problem
}
As reject is not defined, and as you actually don't handle the error. If you don't handle the error, there is no sense in attaching a handler, otherwise you should return a value the chain can continue with, such as:
function(error) {
console.error("Something bad happened", error);
return "An error occured, but we don't mind...";
}
To sum up:
checkCountOnServer()
.then(serverCount => checkPayment())
.then(payment => console.log(payment))
.catch(error => console.error(error));

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