Why this Javascript promise does not work? - javascript

I am Learning about promises.
app.get('/message',function(req, res){
var promise = new Promise(function(resolve, reject){
resolve("hi");
});
promise.then(function(message){
res.json(message);
})
});
This works good.
Though This is too simple. To write something 'lengthy' I moved the code out of app.get() and tried to return the message from the external function... like this:
app.get('/message',function(req, res){
var message = message(); // I also tried wrapping this in promise and calling `res.json` in `promise.then()` but no luck
res.json(message);
});
function message(){
var promise = new Promise(function(resolve, reject){
resolve("hi");
});
promise.then(function(message){
return message;
})
}
So why doesn't the return statement in the message() function return the message ? and what's the best practice to move such promising code out of my route functions?

First, you have a local variable named message which masks the module level variable which has the same name and references a function. You need to rename one of them.
Then: You don't have a return statement for the message function, so it returns undefined.
If you want to get the result of the promise back in the callback function you pass to get then you need to:
Return the promise
Call then on it
Use res.json(...); inside the function you pass to then
For example:
app.get('/message',function(req, res){
var my_message = message();
my_message.then(function (data) {
res.json(data);
});
});
function message(){
var promise = new Promise(function(resolve, reject){
resolve("hi");
});
return promise;
}

Your message function doesn't return anything.
You could do:
app.get('/message',function(req, res){
message().then(function (message) {
res.json(message);
}
});
function message() {
return new Promise(function(resolve, reject){
resolve("hi");
});
}
Also, be careful to not use the same names for multiple variables, since it makes the code error-prone due to less readabililty.

You can return promise from your message function and use async/await on it like:
app.get('/message', async function(req, res){
var msg = await message();
res.json(msg);
});
function message() {
return new Promise(function(resolve, reject){
resolve("hi");
});
}
Like:
function message() {
return new Promise(function(resolve, reject) {
setTimeout(resolve, 1500, 'hi');
});
}
async function go() {
console.log('Async call started...');
var msg = await message();
console.log(msg);
}
go();

The function message does not return the created promise.
Normally you'd have an error saying: cannot read property .then of undefined
function message(){
var promise = new Promise(function(resolve, reject){
resolve("hi");
});
return promise.then(function(message){ // This will return the initial promise. Due to to the .then, that promise is chained into resolving into the message
return message;
})
}
It could be shorted though (in case you do not want the .then in your message function.
Just return the promise then:
function message(){
return new Promise(function(resolve, reject){
resolve("hi");
});
}

Related

Conditional promise in JS

I am trying to reduce the need for multiple functions, especially as many have a promise that is doing the same thing. However, I am looking to add a condition based on props from a parent.
For example I have a function
example
.doSomething()
.then(something => {
example.createSomething(something)
});
But how can I add a condition that changes .doSomething() from props of somethingElse to .doSomethingElse()?
Therefore, if somethingElse === true the function will be
example
.doSomethingElse()
.then(something => {
example.createSomething(something)
});
I am writing this in my phone don't blame me, might tidy up later.
Promise.resolve(somethingElse ? example.doSomethingElse() : example.doSomething())
.then(...
if you think writing twice example is tedious
Promise.resolve(example[somethingElse ? "doSomethingElse" : "doSomething"]())
.then(...
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
By #Phil
if both(all) functions return a Promise
can simply do
example[somethingElse ? "doSomethingElse" : "doSomething"]().then(...
Note that it means Promise.resolve above can even handle non-Promise return value
You can use Promise.all method
let cleaRoom = function(){
return new Promise(function(resolve, reject){
resolve('room is cleaed')
})
}
let removeGarbage = function(message){
return new Promise(function(resolve, reject){
resolve(message + ' garbage is removed')
})
}
let wonIcecream = function(message){
return new Promise(function(resolve, reject){
resolve(message + ' won the icecream');
})
}
Promise.all([cleaRoom(),removeGarbage(),wonIcecream()]).then(function(){
console.log('finished all');
})

Javascript Promise push value into array (only from function or outside?)

I have some promises and a Promise.all:
array = [];
var one = new Promise(function(resolve, reject) {
// Do stuff
setTimeout(function() {
resolve('One Done');
array.push('one');
}, 5000);
});
var two = new Promise(function(resolve, reject) {
// Do Stuff
resolve('Two Done');
array.push('two');
});
Promise.all(array).then(values => {
console.log(values);
});
We know this doesn't work because array.push needs to be outside.
I currently have a few functions which I need to have called by promises so that finally I can have it in Promise.all.
Would it be advisable to call the function from inside the promise like this:
function dosomething() {
// does something
array.push('something');
}
var mypromise = new Promise(function(resolve, reject) {
dosomething();
resolve('Did something');
});
Or is there a more advisable way to do this?
Promise.all waits for an array of Promises. In your example, you are always pushing string types into an array. This obviously won't work. In your first example, you want to push the promises themselves:
array = [];
var one = new Promise(function(resolve, reject) {
// Do stuff
setTimeout(function() {
resolve('One Done');
}, 5000);
});
array.push(one);
var two = new Promise(function(resolve, reject) {
// Do Stuff
resolve('Two Done');
});
array.push(two);
Promise.all(array).then(values => {
console.log(values);
});
As long as the array contains Promise objects, Promise.all will work as expected.
Promise.All expects an array of promises, and will wait until all promises are fullfilled, providing you with the results of each Promise or a catch if any of them fails.
You can resolve them with any type of object if you are willing to resolve it with more than just a string, and you can use the results afterwards in any way you want, so you could avoid messing with the array inside from the promise and instead resolve the "work item" as a unit and use all required results after the async evaluation.
This will also ( i think ) make the code cleaner and more managable.
You could instead try to do this:
var valuesArray=[];
var prom1 = new Promise(function(resolve, reject) {
// Do stuff
setTimeout(function() {
resolve({ msg: 'One Done', data : 'one'});
// array.push('one');
}, 5000);
});
var prom2 = new Promise(function(resolve, reject) {
// Do Stuff
resolve({ msg: 'Two Done', data : 'two'});
// array.push('two');
});
var promisesArray= [prom1,prom2];
Promise.all(promisesArray).then(values => {
// do stuff with values here
console.log(values[0].msg);
console.log(values[1].msg);
valuesArray.push(values[0].data);
valuesArray.push(values[0].data);
});
I think it would be clearest if you called Promise.all with the array of Promises, with each Promise resolving to the desired value, no outer array nor push at all:
var one = new Promise(function(resolve, reject) {
// Do stuff
setTimeout(function() {
console.log('One Done')
resolve('one');
}, 1000);
});
var two = new Promise(function(resolve, reject) {
// Do Stuff
console.log('Two Done');
resolve('two');
});
Promise.all([one, two]).then(arr => {
console.log(arr);
});
If you need both values (the 'One Done' and the 'one'), you can resolve the initial promises with an array with both values, doing whatever you need to with the 'One Done', and then resolving with the 'one' to be chained with array created by Promise.all:
const logAndReturn = ([logStr, finalResolveStr]) => {
console.log(logStr);
return finalResolveStr;
}
var one = new Promise(function(resolve, reject) {
// Do stuff
setTimeout(function() {
resolve(['One Done', 'one']);
}, 1000);
});
var two = new Promise(function(resolve, reject) {
// Do Stuff
resolve(['Two Done', 'two']);
});
Promise.all([
one.then(logAndReturn),
two.then(logAndReturn),
]).then(arr => {
console.log(arr);
});

The example of promises and then

Recently i heard 'promises' and tried to learn how it works and say...
it's not working well.
function example(){
return new Promise(function(){
var i=0;
while(i<5000){console.log(i);i++;}
})
}
example()
.then(
function(){
console.log('done')
},
function(){
console.log('error')
});
it writes 1-4999 but never writes 'done' or 'error'.. how can I make it write 'then' clause?
Your kind reply would be appreciated.
Promises gets two arguments: resolve & reject that will be the functions to be executed as the defined at the .then() & .catch(). So to be able get print the 'done' or 'error' You should do something like this:
function example(condition){
return new Promise(function(resolve, reject){
var i=0;
while(i<5000){console.log(i);i++;}
if(condition){
resolve();
} else {
reject();
}
})
}
example(true).then(function(){console.log('done')},function(){console.log('error')});//Prints 'done'
example(false).then(function(){console.log('done')},function(){console.log('error')});//Prints 'error'
function example() {
return new Promise(function(resolve,reject) {
var i = 0;
while (i < 5000) {
console.log(i);
i++;
}
resolve(i);
})
}
example()
.then(
function() {
console.log('done')
},
function() {
console.log('error')
});
You need resolve, reject callbacks. In your code your Promise always stays in pending state.
Something like... https://www.promisejs.org/patterns/
Ex.:
function example() {
return new Promise(function(resolve, reject){
try{
var i = 0;
while(i < 5000){
console.log('proccess',i);
i++;
}
resolve(i);// an if, to resolve or reject...
} catch(error) {
reject(error);
}
});
}
console.log('will call the promise');
example().then(function(success){
console.log('caller promise result', success);
}).catch(function(error){
console.log('if some problem, catch',error.toString());
});
console.log('Here, will be before or after the promise resolves');

One Promise for Multiple Promises - Concurrency Issue

In the method "myMethod" of my "gulpfile.js" I want to create multiple Promises. The quantity depends on the array size (method parameter). When I call the method I want to make sure that all promises are fulfilled before I continue. I would prefer to return not before all promises are fulfilled.
Please have a look at the last five lines of code.
Dependencies
var promiseAll = require('gulp-all');
var del = require('del');
var deleteEmpty = require('delete-empty');
gulp-all | del | delete-empty
Helper Method
var oneForAllPromises = function(promises){
var promAll = promiseAll(promises);
promAll.then(function(param) {
console.log('foo');
}, function(err) {
console.error('foo');
});
return promAll;
}
Problematic Code
var myMethod = function(array1, array2){
var promise = del(array1, {force: true});
promise.then(paths => {console.log('foo');});
var promises = [];
promise.then(()=>{
for(var i=0; i<array2.length; i++){
promises[i] = new Promise(function(resolve, reject) {
deleteEmpty(array2[i], {force: true},
function(err, deleted){
if(err){
console.log('foo');
reject
}else{
console.log('foo');
resolve
}
}
);
});
}
});
// PROBLEM: Returns empty promises array
console.log("promiesesLENGTH: "+promises.length); // promiesesLENGTH: 0
// Create one promise for all the promises
return oneForAllPromises(promises);
}
At the time of the console.log, the first promise promise = del(array1, {force: true}); is not yet finished, so none of the code in the then is yet executed. That's why your promises are empty.
You can simply return in a then another promise:
var myMethod = function(array1, array2){
var promise = del(array1, {force: true});
return promise.then(() => {
return Promise.all(array2.map(array2value => {
return new Promise(function(resolve, reject) {
deleteEmpty(array2value, {force: true}, (err, deleted) => {
if (err) {
reject(err);
} else{
resolve()
}
});
});
}
});
}

JS ES6 Promise Chaining

I'm trying to learn how to use promises, but am having trouble comprehending the chaining. I assume that with this code, both promises will run. Then when I call test.then() it should know that test has resolved and pass the resolve data to then().
Once that function finishes, it goes onto the next then(), repeating the same process with the test2 promise.
However, I can only get it to print out the first promise results, not the second. Any ideas what is missing here?
var test = new Promise(function(resolve, reject){
resolve('done1');
});
var test2 = new Promise(function(resolve, reject){
resolve('done2');
});
test
.then(function(data) {
console.log(data);
})
.then(test2)
.then(function(data) {
console.log(data);
});
Your first .then call is returning undefined, whereas any subsequent .then is expecting a returned promise. So you'd need to change your code to:
var test = new Promise(function(resolve, reject){
resolve('done1');
});
var test2 = new Promise(function(resolve, reject){
resolve('done2');
});
test
.then(function(data) {
console.log(data);
return test2;
})
.then(resultOfTest2 => doSomething)
.then(function(data) {
console.log(data);
});
You need to return next promise from the then callback:
test.then(function(data) {
console.log(data);
return test2;
}).then(function(data) {
console.log(data);
});
Summary:
The basic concept of promise chaining with promises is that every then / catch method on a fulfilled promise returns another promise. It works in the following manner:
When a promise is resolved the callback passed in the then method is called. The then method wraps the value which is returned in its callback in a resolved promise and returns this resolved promise.
When a promise is rejected the callback passed in the catch method is called. The catch method wraps the value which is returned in its callback in a rejected promise and returns this rejected promise.
Example:
Before fully understanding the concept of chaining multiple then methods it is important to know what exactly the return values of then and catch are. Take the following example:
let prom1 = new Promise((res, rej) => {
res('res');
});
const resolvedProm1 = prom1.then((val) => {return val});
// setTimeout needed for the promise to actually be resolved
setTimeout(() => console.log(resolvedProm1));
let prom2 = new Promise((res, rej) => {
rej('rej');
});
const resolvedProm2 = prom2.catch((err) => {throw err});
// setTimeout needed for the promise to actually be rejected
setTimeout(() => console.log(resolvedProm2));
We can observe the status of the promises in the chrome devtools:
What basically happens is that in a then or catch callback is the following:
Any value returned in a then or catch callback is wrapped in Promise.resolve() and a new resolved promise is returned.
Any error thrown in a then or catch callback is wrapped in Promise.reject() and a new rejected promise is returned.
Because we are getting returned a rejected or resolved promise object we can repeat the cycle and call the then or catch method on it again. For example:
const prom = new Promise((res, rej) => {
if (Math.random() > 0.5) {
res('success');
} else {
rej('error');
}
});
prom.then((val) => {
return val;
}).then((val) => {
return val
}).then((val) => {
console.log(val)
}).catch((err) => {
console.log('err');
})
This calling of then and catch methods which are executed in their respective order is called promise chaining. It is a very useful technique to make working with asynchronous code easier, especially if multiple asynchronous operations need to be performed which are dependend on each others data.
you need to return the other promise(test2) in the first promise (test1) to allow for chaining:
var test = new Promise(function(resolve, reject){
resolve('done1');
});
var test2 = new Promise(function(resolve, reject){
resolve('done2');
});
test
.then(function(data) {
console.log(data);
return test2;
});
You may also want to try -
let test = new Promise(function(resolve, reject){
resolve('done1');
});
let test2 = new Promise(function(resolve, reject){
resolve('done2');
});
try {
let logOne = test();
let logTwo = test2();
console.log(logOne);
console.log(logTwo);
} catch(error) {
console.error(error);
}
In this way, you can also properly handle any promise dependencies. For example if test one relied on test two's data your could -
try {
let logOne = test();
let logTwo = test2(logOne);
console.log(logOne);
console.log(logTwo);
} catch(error) {
console.error(error);
}

Categories