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');
})
Related
I have a function called "test_sheet" that is supposed to return a value. that value will then be passed to a tester function which will tell me if I passed or failed the test.
inside my "test_sheet" I have a few async operations which are handled by promises.
now, how can I return a (non-promise) value from my test_sheet function.
function test_sheet()
{
//all my logic will go here
new Promise(function(resolve, reject)
{
//simulating an async operation
setTimeout(() => resolve(true), 1000);
})
.then(function(res){return res});
}
function tester()
{
//not allowed to change this function in any way
if(test_sheet() == true)
console.log("pass!");
else
console.log("fail!");
}
tester();
Is there any better way of doing this?
Well, technically it is possible, tester() may reamain intact:
var test_sheet=false;
function start_test()
{
//all my logic will go here
new Promise(function(resolve, reject)
{
//simulating an async operation
setTimeout(() => resolve(true), 1000);
})
.then(res => {
test_sheet=true;
tester();
});
}
function tester()
{
//not allowed to change this function in any way
test_sheet == true ? console.log("pass!") : console.log("fail!");
}
//tester();
start_test();
But the test starts with start_test() now, and test_sheet became a variable, with the sole purpose of acting as an argument - which could not be added to testing() without modifying it.
A nonworking bad design is transformed to working bad desing this way.
test_sheet() always returns a promise so try to get it resolved using async await or .then which feeds into the tester() function.
call you function this way:
test_sheet().then(function(test_sheet){
tester(test_sheet)})
for this you need to pass the boolean return value from test_sheet() to tester(test_sheet)
If you handle asynchronous code you have to use promise or callback and handle with async/await to change them to synchronous code
For example
function test_sheet()
{
//all my logic will go here
return new Promise(function(resolve, reject) {
//simulating an async operation
setTimeout(() => resolve(true), 2000);
})
}
async function tester()
{
//not allowed to change this function in any way
await test_sheet() == true ? console.log("pass!") : console.log("fail!");
}
tester();
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");
});
}
I just implemented my first function that returns a promise based on another promise in AngularJS, and it worked. But before I decided to just do it, I spent 2 hours reading and trying to understand the concepts behind promises. I thought if I could write a simple piece of code that simulated how promises worked, I would then be able to conceptually understand it instead of being able to use it without really knowing how it works. I couldn't write that code.
So, could someone please illustrate in vanilla JavaScript how promises work?
A promise is basically an object with two methods. One method is for defining what to do, and one is for telling when to do it. It has to be possible to call the two methods in any order, so the object needs to keep track of which one has been called:
var promise = {
isDone: false,
doneHandler: null,
done: function(f) {
if (this.isDone) {
f();
} else {
this.doneHandler = f;
}
},
callDone: function() {
if (this.doneHandler != null) {
this.doneHandler();
} else {
this.isDone = true;
}
}
};
You can define the action first, then trigger it:
promise.done(function(){ alert('done'); });
promise.callDone();
You can trigger the action first, then define it:
promise.callDone();
promise.done(function(){ alert('done'); });
Demo: http://jsfiddle.net/EvN9P/
When you use a promise in an asynchronous function, the function creates the empty promise, keeps a reference to it, and also returns the reference. The code that handles the asynchronous response will trigger the action in the promise, and the code calling the asynchronous function will define the action.
As either of those can happen in any order, the code calling the asynchronous function can hang on to the promise and define the action any time it wants.
For the simplicity to understand about the promises in Javascript.
You can refer below example. Just copy paste in a new php/html file and run.
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript">
function test(n){
alert('input:'+n);
var promise = new Promise(function(fulfill, reject) {
/*put your condition here */
if(n) {
fulfill("Inside If! match found");
}
else {
reject(Error("It broke"));
}
});
promise.then(function(result) {
alert(result); // "Inside If! match found"
}, function(err) {
alert(err); // Error: "It broke"
});
}
</script>
</head>
<body>
<input type="button" onclick="test(1);" value="Test"/>
</body>
</html>
Click on Test button,
It will create new promise,
if condition will be true it fulfill the response,
after that promise.then called and based on the fulfill it will print the result.
In case of reject promise.then returns the error message.
Probably the simplest example of promises usage looks like that:
var method1 = (addings = '') => {
return new Promise(resolve => {
console.log('method1' + addings)
resolve(addings + '_adding1');
});
}
var method2 = (addings = '') => {
return new Promise(resolve => {
console.log('method2' + addings)
resolve(addings + '_adding2');
});
}
method1().then(method2).then(method1).then(method2);
// result:
// method1
// method2_adding1
// method1_adding1_adding2
// method2_adding1_adding2_adding1
That's basic of basics. Having it, you can experiment with rejects:
var method1 = (addings = '*') => {
return new Promise((resolve, reject) => {
console.log('method1' + addings)
resolve(addings + '_adding1');
});
}
var method2 = (addings = '*') => {
return new Promise((resolve, reject) => {
console.log('method2' + addings)
reject();
});
}
var errorMethod = () => {
console.log('errorMethod')
}
method1()
.then(method2, errorMethod)
.then(method1, errorMethod)
.then(method2, errorMethod)
.then(method1, errorMethod)
.then(method2, errorMethod);
// result:
// method1*
// method2*_adding1
// errorMethod
// method2*
// errorMethod
// method2*
As we can see, in case of failure error function is fired (which is always the second argument of then) and then next function in chain is fired with no given argument.
For advanced knowledge I invite you here.
please check this simple promise code. this will help you to better understand of promise functionality.
A promise is an object that may produce a single value some time in the future: either a resolved value, or a reason that it’s not resolved. A promise may be in one of 3 possible states: fulfilled, rejected, or pending. Promise users can attach callbacks to handle the fulfilled value or the reason for rejection.
let myPromise = new Promise((resolve, reject)=>{
if(2==2){
resolve("resolved")
}else{
reject("rejected")
}
});
myPromise.then((message)=>{
document.write(`the promise is ${message}`)
}).catch((message)=>{
document.write(`the promise is ${message}`)
})
check this out
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);
}
The following code gets stuck:
var Promise = require('promise');
var testPromise = function(){
return new Promise(function(fulfill, reject){
element.all(by.repeater('item in menu.items')).first().then(function(el){
console.log('test f');
fulfill(el);
console.log('test fe');
});
});
};
... called by the following:
testPromise().then(function(el){
console.log('test successful '+el);
});
The console prints
test f
test fe
And get stuck no more code is executed. It never reaches the then although fulfill has been called.
if using nested promises is an anti pattern then how do I do the following without a nested promise:
var getMenuItemEl = function(itemName){
return new Promise(function(fulfill, reject){
var elFound;
element.all(by.repeater('item in menu.items')).then(function(els){
async.each(els, function(el, callback){
el.getText().then(function(text){
console.log('getMenuItemEl:'+text);
if(text === itemName){
elFound = el;
}
callback();
});
}, function(err){
console.log('complete '+elFound);
if(elFound){
console.log('fulfill');
fulfill(elFound);
console.log('after fulfill');
}else{
reject('no item found');
}
});
});
});
};
This also gets stuck after the fulfill has been called
if using nested promises is an anti pattern then how do I do the following without a nested promise
You would not use the async library. Since all your methods (element.all(), el.getText() etc) do already return promises, you don't need to go back to node-style error callbacks. From my "rules for promises",
every async function (even if it is a callback) should return a promise, and use your libraries' methods to compose them. You really don't need to call the Promise constructor on your own. That iteration you are doing there can be easily done by a map over the els, then collecting all the single promises together with Promise.all.
function getMenuItemEl(itemName) {
return element.all(by.repeater('item in menu.items'))
.then(function(els){
return Promise.all(els.map(function(el) {
return el.getText()
.then(function(text){
console.log('getMenuItemEl:'+text);
return (text === itemName) ? el : null;
});
}));
})
.then(function(foundEls) {
for (var i=0; i<foundEls.length; i++)
if (foundEls[i] != null) {
console.log('fulfill');
return foundEls[i];
}
throw new Error('no item found');
});
}
The following code solves my problem, mainly due to my lack of knowledge of the protractor api
var doClickMenuItemEl = function(itemName){
return element.all(by.repeater('item in menu.items')).filter(function(elem, index) {
return elem.getText().then(function(text) {
return text === itemName;
});
}).then(function(els){
els[0].click();
});
};
It also says on https://github.com/angular/protractor/issues/379 that
Yes, this is inherited from webdriver promises, which are not quite promise A+ compliant, unfortunately.