[object Promise] showing up?

@stucork Seeing an [object Promise] come up in some output. It’s obviously a timing related thing related to the custom dictionary in Skulpt work: [Fixed] Odd behavior with a custom dictionary in Skulpt

But, I’m having trouble working out why I’m seeing the particular behavior I’m seeing. This is clearly just a case of me not knowing enough about how Javascript works, so I’m hoping you can provide an explanation.

Here’s a clone that shows the behavior: [Fixed] Odd behavior with a custom dictionary in Skulpt

When you run it you should see [object Promise] displayed. Clicking Refresh Display shows the actual output with the parchment background.

What’s happening to display that parchment background is that I’m passing the following bbcode to a parser: [bg="top left repeat" media="parchment" radius="5px"]This should be on a parchment background[/bg]

The bbcode parser is taking the bg tag and replacing it with a span of this form: <span style="display: inline-block; background: url(https://vungdvcnmfn5avnz.anvil.app/debug/FH73U2XO3LNK4HGDOUKEGTS6SX2J4MUZ%3D45G55LDPR7XPP3LKYTTLOPYB/_/lm/table-media/4c23bde0154a8221c9b342c266260a64/32579823/crumpled-rice-paper.jpg?s=) top left repeat;border-radius: 5px;">This should be on a parchment background</span>

The URL inside that span is what’s being fetched through the custom dict via a server call. On the first try to fetch a specific URL from the custom dict, it has to make a server call. I expect that first call to have a delay in it.

I’m at a loss to work out why the entire span is being replaced with a Promise on that first call when it has to fetch the URL from the server.

Looking at the javascript library source code for the parser - it doesn’t do asynchronous code.

When you do a lazy fetch for media to the server - you’re giving the JavaScript library a promise. (In the docs you might have seen the phrase something like - blocking code in Python becomes a promise in JavaScript). But the library isn’t written to be asynchronous so you end up with the text output of a Promise as it tries to parse it.

In JavaScript asynchronous code has to be cooperative. And the library you’re using doesn’t know it’s supposed to cooperate.

Anvil makes asynchronous stuff happen without you thinking about it.

I would consider pre/post processing the lazy media objects before/after giving the JavaScript parser the text. Anvil knows how to do the asynchronous/lazy part and then you can give the parser something that it doesn’t need to handle in an asynchronous/lazy way.

That’s why it’ll work the second time - by then the asynchronous stuff is all done.

1 Like

Thanks for the explanation! I unfortunately can’t try that at the moment, since the problem with the client-side dict’s in operator seems like it showed up again. It was working great this morning, but at some point during the day the behavior reverted.

Looks like I’ll need more of a rewrite to avoid the tricky bit with the client side dict doing a server call anyway, which’ll work fine with preprocessing to fetch the info from the server to avoid the promise.

Edit: avoiding the client side dict was easier than I’d thought once I worked in the preprocessing for media URLs. Everything’s working now.

2 Likes