iodide-project / iodide-project/iodide

proposal: create a JS async language plugin to play with top-level-ish await

Open
#1,841 7 comments 0 reactions 0 assignees View on GitHub
proposal
Dominant language
JavaScript
Stars
1.5k
Forks
145
PR merge metrics
No merged PRs in 30d

Description

Working iteratively with async javascript is not always very pretty if you're coming from a data science background. We've built a number of workarounds that help:

1.) fetch chunks make it simple to load data from the web + from the iodide server, which removes the programmatic headaches of working with async js
2.) if your return value of a chunk is a Promise, iodide awaits until the Promise resolves before moving onto the next enqueued chunk

But there's probably more we can do, or at least experiment with. These aren't particularly natural ways of handling data pulling in all situations.

If #1840 lands, we should be able to better parametrize language chunks and try out new ideas. One idea would be to create an async js plugin, which actually just wraps the chunk contents in an async `Function`, runs it, and then puts whatever is the return value into `window[returnVarName]` (of which `returnVarName` is defined as a flag).

This would allow some workflows that are currently ~difficult~ boilerplatey with vanilla `js` chunks:

```

%% async-js returnVarName="crunchedData"

// even though we use var here, it will be scoped to the chunk only because of how
// Function works.
var data = await fetchMyData()

var moreData = await combineTheseDataSources(data, etc.);

moreData // this is the return value added to window.crunchedData
%% js

// plot crunchedData

plot(crunchedData, ...)

```

I once the flags-in-evaluators issue gets fixed, this might be the cheapest way to use a language plugin to explore this idea. If we like it and are okay with the tradeoffs, and feel that it is valuable enough for Iodide users, we might explore just adding an `async` flag into iodide `js` chunks that replicates this behavior.

The tradeoffs primarily are around scoping – `var` doesn't assign globally as it does elsewhere, nor would something like `x = await fetch()...`. This is a bit of a dealbreaker for casual data science, I think, sine users are still expecting the REPL experience. Unless something speeds up [this TC39 proposal](https://github.com/tc39/proposal-top-level-await) I don't know any way around this.

Contributor guide

Open the contributing guide

Research direction

Start by reviewing the flags-in-evaluators work in #1840 and the existing JavaScript chunk/plugin entry points. Prototype the proposed async-js behavior with an async Function and returnVarName, then evaluate the scoping tradeoffs and whether the workflow works for Iodide users.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.