0

I have the following piece of code (+layout.svelte):

import { getLang } from "$lib/locale";
import { browser } from "$app/environment";

const loadLang = async () => {
    if (browser) {
        // return await getLang(document.documentElement.lang, "home").then( function (data: any) {
        //  const nav = JSON.stringify(data.nav);
        //  console.log(nav)
        //  return nav;
        // });
        const initLocale= await getLang(document.documentElement.lang, "home");
        return initLocale.json();
    }
};

const a = loadLang();
console.log(a);

What this snippet does is detect the browser language, the route requested and then searches for the correct JSON file corresponding to the language and the page. But there is a problem, I am unable access the language data of the async loadLang() to use it in the component's HTML elements and there is no way for me to actually do that other than what many answers here stated (which is not what i'm looking for), What I want is a way to access the returned value of the aforementioned function and use it in the HTML elements?

retr0cube
  • 7
  • 1
  • 3
  • Please see [How do I return the response from an aynchronous call](https://stackoverflow.com/q/14220321/438992), which this duplicates. – Dave Newton Aug 14 '23 at 18:19
  • @DaveNewton I already saw it, didn't help me resolve the issue, if you read the question I asked at the end you'll see how this differs compared to what you provided (especially the part of using the value in an HTML element inside a svelte component) – retr0cube Aug 14 '23 at 18:33
  • 1
    Then please update your post to explain that you already looked at that post and how it differs from your problem [in your post](/help/how-to-ask), because that's important to know, especially for _future_ visitors who are trying to find an answer to their own, similar, problem. That said, I'm not sure I understand the problem: why does `a` not await the async function's return value? (also, why is it a global const arrow function when it doesn't need to preserve the declare-time `this`? But that's more of a "this is odd, but not _wrong" thing) – Mike 'Pomax' Kamermans Aug 14 '23 at 18:53
  • Does this answer your question? [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Keith.Abramo Aug 14 '23 at 18:54

2 Answers2

0

There is native syntax (with many variants) for awaiting promises in markup:

{#await loadLang() then lang}
  <span>{lang.someValue}</span>
{/await}

The other alternative would be to declare a variable in the top level scope and set after the data is loaded. Of course it will be undefined or whatever else you initialize it to, first. This then usually would be combined with {#if}:

let lang;
loadLang().then(l => lang = l);
{#if lang}
  <span>{lang.someValue}</span>
{/if}

Having a guard on browser there is not great. You might want to move the loading of the data to a +layout load function, so it is passed as the data prop and can be used during SSR and CSR and is available to every page using the layout.

Instead of using document.documentElement.lang use the Accept-Language header of the request on the server.

Loading the data before the page is served/rendered also would prevent potential layout shifts or loading indicators.

H.B.
  • 166,899
  • 29
  • 327
  • 400
  • Hey @H.B. ! Thanks for the answer, very good advice. I remember trying this but getting "undefined" in the browser, but I'm not sure. I will try this and if it works i'll flag it as the correct answer – retr0cube Aug 14 '23 at 23:17
-1

Your async function will return a Promise. You should handle its result with a callback.

Like this:

loadLang().then(result => {
  // and here do whatever you want with the result, log it for example
  console.log(result);
})