Promises, Promises

#Promise #Asynchronous #then #beer #wife velo

In Velo, there are a number of cases where code is not necessarily executed sequentially. This is called asynchronous code execution. Velo uses Promises to handle asynchronous code. Web modules, fetches (wix-fetch), and database queries, are some of the places where you will need to handle Promises.

This may sound complicated or a bit weird, but the concept of Promises is actually really quite simple. Look at it this way…

  • My wife asks me to take out the trash :: the request or query

  • I say, “yes dear” :: the promise

  • The wife of course doesn’t expect this to happen any time soon, so immediately after the promise she keeps on doing whatever it is she’s doing.

  • Eventually (after I’ve had a beer or two) I take out the trash which is the fulfillment , or .then() , of the promise .

Let’s look at some loosely defined pseudo-code to see how this might work in Javascript:

let promise = request(“take out the trash”);
let status = full;
promise.then(function(result) {
    status = result; // result = empty
    console.log(status); // “empty”
}, function(err) {
    // “fatal” error - fell asleep after the fourth or fifth beer
    console.log(err); // Error: “wife stomps angrily around house"
});
console.log(status); // still “full"

As you can see, if my wife was to do a console.log(status) directly after I promise to take out the trash, the trash can would show up full (probably for a considerable period of time). However, after I’ve had a few beers, I take out the trash and my promise has been fulfilled. That is, we are now in the .then() handler and console.log(status) shows the trash can is empty.

I hope this helps. And don’t tell my wife - although I suspect she already knows.

For further details, see the article Velo: Working with Promises.

16 Likes

Yisrael, good idea. It´s necessary, for many (inc. me) have had a hard time wrapping their heads around the concept of the async behaviour. I was playing with the same idea, slightly different from yours, which stresses the difference between sequential and async. I hope you allow me:

The case
Let´s assume a business with a shipping department, putting items in boxes and shipping them off. For one package, the address is not filled out. So the guy calls to the accounting department.

The sequential way (Visual Basic, ASP Classic, etc)
“Hello, Jeff here, from Shipping. Listen, can you get me the address for order #12345, because it´s missing?”
“Sure, hold on, I will get it for you, don´t put the phone down.”
Now Jeff waits on the phone, he cannot do anything else. After 5 minutes:
“Jeff, you still there?”
“Yes, I´m still here”
“OK, the address is …”
“Thanks”
Jeff hangs up the phone and continues with the package with the missing address.

The async way (Javascript)
“Hello, Jeff here, from Shipping. Listen, can you get me the address for order #12345, because it´s missing?”
“Sure, but I´ve got a couple of other things to do, let me call you back when I found it, OK?”
“Promise?”
“Promise!”
Here, the only thing Jeff got was a Promise for a Call Back. Nothing else. So now, in the mean time, he just continues with the next package. Then, five minutes later (or ten, or 60, you never know), he gets his call back:
“OK, the address is …”
Now Jeff goes back to the package, puts the address on it, ready.

So when the Wix Documentation says some function delivers a Promise, take that very literally: you do not get the requested value yet, you have to wait for the promised call back.

Example: getEmail()
The Wix doc says:

Description
The getEmail() function returns a Promise that resolves to the email address of the user that is logged in or rejects if the current user is not logged in.

But, I see many people on the forum do something like this:

import wixUsers from ‘wix-users’;

// …

let user = wixUsers.currentUser;

let email = user.getEmail();
console.log(“email=” + email);
} );
The email will be empty, because user.getEmail() DOES NOT RETURN THE EMAIL IMMEDIATELY, it just returns a Promise. SO you have to WAIT for it to resolve. And you can wait in 2 different ways:

  1. using .then (which should have been called “.when_it_calls_back”, but that is a bit too long)

import wixUsers from ‘wix-users’;

// …

let user = wixUsers.currentUser;

user.getEmail()
.then( (email) => {
let userEmail = email;
} );

  1. using async/await

This lets you do it the first (here erroneous) way, making Javascript behave more like a sequential language. Search the forum for more info.

Hope this clarifies a bit how Promises work.

hi bro … i have problem to update record and delete it in the collection
this is code i tried many times with out useless

export function button28_click(event, $w) {

let allupdate = {
“workplace”: $w(“#input3”).value,
“exyears”: $w(“#input4”).value
};

wixData.query(“training”)
.eq(“name”, $w(“#input5”).value)
.find()
.then( res => {
wixData.update(“training”,allupdate)
let items = res.items;
console.log(res.items[0].name);
console.log(res.items[0].level);
console.log(res.items[0].moreve);
console.log(res.items[0].id);
});
}

by the way i am beginner wix code

i hope your experience resolve this issue.

thanks.

@yisrael-wix - I’ve noticed a very strange behaviour with promised and async when called from a front-end page to a backend jsw file. Essentially, when all the async functions are in the client code everything works correctly, but when I export from a JSW page things lose sync. Ideas ?

Functions cannot be called from a frontend file to a backend jsw file. You can only call backend code from frontend code.

this is one of my favourite explanations of asynchronous code execution!

hi Yisrael,
yours is absolutely the funniest and easiest way to understand async call. I ‘liked’ your post. I also hope you might help me for a case I am working on.
Basically, I need to run async call in a loop, and i need to make sure all aync call fulfilled before my loop finish. otherwise it’s in a uncontrollable situation.
it’s a piece of code, to remove items from shopping cart. I have a list of items to loop through, and in each loop, i call wixStores.removeProductFromCart. When i have more than 2 items to remove, loop done but async not, i end up have items supposed to be removed left in cart. Below is a code in skeleton. Hopefully you can give me advise on that. I really appreciate.

for (i = 0; i < removedItems.length; i++) {

console.log("doing # "+i);

wixStores.removeProductFromCart(removedItems[i]._id) .then((updatedCart) => {

//nothing

}).catch((error) => {

// Product not removed

console.error(error);

});

}

}

amazing teacher

Hi
Here’s my code

wixUsers . register ( email , password )
. then ( async () => {
$w ( “#success” ). expand ();
$w ( “#continuebtn” ). expand ();
$w ( “#registerbtn” ). disable ();

        }) 
        . **catch** (( err ) => { 
            $w ( "#error" ). expand (); 
            console . log ( err ); 
            $w ( "#success" ). collapse (); 
            $w ( "#continuebtn" ). collapse (); 
        }); 

here this works i all other browsers but in safari it does not
the user is created in the dashboard but the code inside .then() not working

Why is that? ONLY IN SAFARI

First, this is the incorrect location for this question.

Second, please observe the community guidelines and refrain from multiple posts on the same topic or question.

I answered your other post regarding this issue.