Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Why does this use top-level await? #30

Closed
doonv opened this issue Jun 12, 2023 · 14 comments
Closed

Why does this use top-level await? #30

doonv opened this issue Jun 12, 2023 · 14 comments
Assignees
Labels
bug Something isn't working

Comments

@doonv
Copy link

doonv commented Jun 12, 2023

It seems unnecessary...

And my framework doesn't seem to support top-level await.

@Offroaders123
Copy link
Owner

Offroaders123 commented Jun 12, 2023

The reading and writing functions have to be async because the Compression Streams API only provides async compression and decompression endpoints, so you can't synchronously compress and decompress files, unfortunately.

@doonv
Copy link
Author

doonv commented Jun 13, 2023

Well I don't need compression. I just need to be able to merge SNBT strings (like {hi: 1b} + {str:"hajjwi"} = {hi:1b, str:"hajjwi"}).

I could just remove the compression and decompression part from the library manually. But that means I won't be able to update the library. So I don't really know what to do.

@Offroaders123
Copy link
Owner

Oh alright then, that works without await luckily. stringify() and parse() don't require the use of await, only read() and write() do.

@doonv
Copy link
Author

doonv commented Jun 14, 2023

Well I thought of that but it seems I cant just do import { parse, stringify } from "nbtify". It still gives me an error. But I think I might have a solution

@Offroaders123
Copy link
Owner

Where are you importing these, in Node, or in the browser? Sounds like it might be the "nbtify" module reference. If you're in the browser, try loading it from a CDN module provider site, like JSDelivr.

<script type="module">
  import { parse, stringify } from "https://cdn.jsdelivr.net/npm/nbtify/dist/index.min.js";
</script>

Or if your project isn't set up to use <script type="module">, you can use the dynamic import() function instead. Because of the network request requirement for module loading, it's mandatory for the browser to load modules asynchronously, meaning the dynamic import() returns a Promise. You can access the exports of the module once the Promise fulfills, using a .then() function call on the Promise object. The first parameter will be an object with all of the exports for NBTify.

<script>
  import("https://cdn.jsdelivr.net/npm/nbtify/dist/index.min.js").then(NBT => {
    const { parse, stringify } = NBT;
    console.log(parse,stringify);
  });
</script>

I'd personally rather wrap all of my application logic in an async IIFE (immediately invoked function expression) in the event of not being able to use <script type="module">. This allows you to use await, just not at the top level of the script. This makes it easier to read because you don't have to worry about adding any .then() handlers to your Promise objects, you can just await them instead.

<script>
  (async () => {
    const { parse, stringify } = await import("https://cdn.jsdelivr.net/npm/nbtify/dist/index.min.js");
    console.log(parse,stringify);
  })();
</script>

The reason the first example works without any uses of await of .then() calls, is because <script type="module"> scripts are hoisted to run after all other regular <script> scripts.

@doonv
Copy link
Author

doonv commented Jun 14, 2023

It appears that the import { parse, stringify } from "nbtify" thing has fixed itself. Weird.

I'm not gonna question it. I will reopen this issue if I encounter another problem.

@doonv doonv closed this as completed Jun 14, 2023
@doonv
Copy link
Author

doonv commented Jun 14, 2023

Update: Apparently, running the site from npm run dev doesn't work. But using the built version with npm run build && npm run preview works fine. Huh.

@Offroaders123
Copy link
Owner

Interesting. Are you using Vite to build your site?

@Offroaders123
Copy link
Owner

If you have a link to your code or an example of how it's set up, I can try and help debug it with you.

@doonv
Copy link
Author

doonv commented Jun 18, 2023

Actually, I think the question I should be asking is not "Why does this use await" but instead "Why does this use top level await"?
Because this library shouldn't even need top-level await (since all the parts that need await are in async functions). The only place where top-level await is used is here :

const NODE_DEFLATE_RAW_POLYFILL: boolean = await (async () => {
  try {
    new CompressionStream("deflate-raw");
    new DecompressionStream("deflate-raw");
    return false;
  } catch {
    try {
      await import("node:zlib");
      return true;
    } catch {
      return false;
    }
  }
})();

I don't think this is necessary, is it?

@doonv doonv reopened this Jun 18, 2023
@Offroaders123
Copy link
Owner

Aah ok, yeah I can find a way to refactor that part. It should probably work instead just from inside an async function or just be a plain Promise instead. And I guess I pictured that bundlers could manage the use of top-level await, but turns out that's not possible at the moment.

@Offroaders123
Copy link
Owner

Working on this at the moment, going to remove the usage of top-level await. ✅

And my framework doesn't seem to support top-level await.

Just curious, is this because your project needs an older build target to support older platforms/browsers? When lowering the target for NBTify, TypeScript does mention that using top-level await requires the 'module' option set to ES2022 or higher, and the 'target' option set to ES2017 or higher.

TypeScript TSConfig Error

I only ask just because I'm curious what kinds of environments people might be using NBTify in. I've only been doing things in evergreen browsers, and bleeding-edge versions, so support for more modern features hasn't been as much of a concern for me (maybe wrongly), since they can be polyfilled by users as necessary.

Have you had any other build target issues working with NBTify that I should look into? I don't want to use the latest and greatest features if it makes the library hard to use and make cool things with.

Offroaders123 added a commit that referenced this issue Jun 19, 2023
@doonv
Copy link
Author

doonv commented Jun 21, 2023

Commit bb1f6cb fixed the issue! Thanks!

@doonv doonv closed this as completed Jun 21, 2023
@Offroaders123
Copy link
Owner

Great! Thanks again for the feedback here. I'm currently working on publishing this and some other features to a new version on npm.

@Offroaders123 Offroaders123 self-assigned this Jun 21, 2023
@Offroaders123 Offroaders123 added the bug Something isn't working label Jun 21, 2023
@Offroaders123 Offroaders123 changed the title Why does this use await? Why does this use top-level await? Jun 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants