Wrapping Asynchronous (then do) blocks into a Synchronous Function resolves unpredictable results

Thunkable provides an extensive library of calls to external services including Google Docs and Web APIs. These external calls are, by necessity, asynchronous calls. That is, the request is sent to the external serivce, Thunkable block execution continues on it’s merry way, then the external service sends a reply. Thunkable wraps the external calls in in blocks with “Then Do” sections. This is a massive improvement over separate call and response block (MIT App Inventor), but it is not without challenges.

These asynchronous calls are particularly problematic when trying to loop through a list and make an external service call (e.g. Add to Data Source, make a Web API call).

Loops like this result in either Thunkable crashing or erratic results. Wait blocks can help, but the still produce unreliable results.

The blocks below illustrate how you can convert an asynchronous external call into a synchronous function, eliminating the irregularities associated with external calls within loops.

Let’s break it down.

#1 Looping through a collection. This could be any loop, either a collect or a for x to y. Because the example asynchronous call is for a mapping API, it is a list of coordinates.

#2 Wrap the Web API call in a function. To keep the loop working correclty, the web_API call ( asychronous process) is wrapped in a function (aka a facade). By using a function wrapper, it forces the web API call to act like any other synchronized Thunkable block (e.g. Set Value to …).

#3 Call…Waiting. First, and most importantly, the result variable is set to an empty value as the first step in the function. If you don’t do this, nothing will work.


The external call’s results are placed in a Thunkable variable. This acts as a trigger for the next step, the waiting. The Repeat Until loop continues until the Result value is not blank. That keeps Thunkable waiting until the Web_API call finishes, no matter how long that make take. Also notice that regardless of success or error, a Result value is set.

The wait block and label updates are not essential, but help make progress easier to evaluate.

Although this example use the Web API, Data Source call can (should) also be wrapped in this way when looping is required.

As a note to Thunkable Staff ( Steven, domhnallohanlon, Jane, Thunkable Staff) might want to consider a similar built-in strategy. Asynchronous processes is a pretty advanced concept for a tool designed for new programmers. I L-O-V-E that Thunkable came up with a strategy to combine submit and response blocks (a la MIT App Inventor) into a single block. The next logical step is to build the wait into the block so novices can treat Web_API calls like Set Label blocks.

Here’s a remixable link

P.S. I found that occasionally the Web API service (or other asynchronous process) will not respond. The above example will loop indefinitely in that case. To prevent an infinite loop, I added a WaitCounter variable which will trigger a break out of the REPEAT UNTIL frame after a set number of loops. In my case I wait for 10 second (20 loops with a 0.5 second wait).

4 Likes

Nice work! You made a nice logic gate there!

1 Like

Can’t wait to try this out! But 1/2 a second (Wait 0.5 seconds) seems like a long delay. Did you have any luck with shorter delays?

Depends on the call. As you can see from the screen shot, for this web_api, is was about a second to get a response. You can go with any length (1, 0.1, 0.000000001, etc). You could also include no wait at all. I just added the wait to reduce the number of “waiting…” entries in the label.

Yeah, I might try it with no wait or a short delay such as 0.03 seconds. In my case, I don’t need to alert the user so it’s just going to be a background task to make sure the API call or Create Row block completes.

1 Like