1

I am making a a one page web app with JavaScript and TypeScript. I am also using the module system of JavaScript (type="module").

I have a class called Form that takes in an object and creates a Form. I have a module in which I have all the data for Registration form. There is one select in the inputs which have options field. I was those options to be assigned to the array containing names of countries. I am using an API to get the names of the countries. But I am stuck.

Below is my file RegisterFormDialog.ts

const RegisterFormData: IForm = {
   //... Some other props
   inputs: [
      //..Some other objects.
      {
         name: "country",
         type: "select",
         label: "Country",
         options: countries.map(x => x.name) // Here I want result of the api
      }
   ]
};

export const RegisterForm = new Form(RegisterFormData);

export const RegisterFormDialog = new Dialog({
   child: RegisterForm.element,
   title: "Register",
   dismissable: true,
   onClose: () => 5,
   parentElement: qs("#main") as HTMLElement
});

The other file is which have the API function. Its name is GetCountries.ts

export default async function getCountries() {
   return await (await fetch("https://restcountries.eu/rest/v2/all")).json();
}

Now how could I assign the returned value of the data of API to the options property in the object.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
Maheer Ali
  • 35,834
  • 5
  • 42
  • 73
  • 1
    It's not clear how any of what you're showing fits together. `this.options = await getCountries()`, maybe? Give a [mcve]. – jonrsharpe Dec 30 '19 at 19:18
  • @jonrsharpe Yeah this `this.options = await getCountries()` i closest to my need. But problem is I can't use `await` without `async` – Maheer Ali Dec 30 '19 at 19:25
  • Correct, because it's really just a promise, *something* needs to resolve it. – jonrsharpe Dec 30 '19 at 19:26
  • @jonrsharpe So does this mean that if I want this api data inside here I will have change the whole code structure? – Maheer Ali Dec 30 '19 at 19:28
  • That's the deal, yes. – jonrsharpe Dec 30 '19 at 19:29
  • @jonrsharpe Isn't there any alternative? – Maheer Ali Dec 30 '19 at 19:30
  • Observables? Callbacks? See the canonical https://stackoverflow.com/q/14220321/3001761. If you're not comfortable with async you probably don't want to be writing your own SPA framework. – jonrsharpe Dec 30 '19 at 19:31
  • @MaheerAli You need an asynchronous result, it's not possible to grab that and bring it into a fully synchronous context where you can immediately export and have it available synchronously to the rest of your code. If your options depend on a network request, then all code depending on the options is now asynchronous as it can't run until the network request finishes. – Klaycon Dec 30 '19 at 19:33
  • 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) – Heretic Monkey Dec 30 '19 at 19:49

1 Answers1

0

Any function declared as async should be awaited (or use .then()) to use its resolved value.

So you just have to await your getCountries function, too.

options: (await getCountries).map(x => x.name)
Alex Wayne
  • 178,991
  • 47
  • 309
  • 337
  • Its giving error. `'await' expression is only allowed within an async function.ts(1308)` – Maheer Ali Dec 30 '19 at 19:24
  • Yep. Any function that awaits an async function, must also (logically) be async. So that error tells you everything you need to know here. – Alex Wayne Dec 30 '19 at 19:26
  • Top-level await is still in the proposal stage, is it not? This is clearly in the top level from the use of `export`, making one of the variables depended on by the `export` async seems problematic. You'll have to import and resolve a promise to do things this way, per the other answer @MaheerAli – Klaycon Dec 30 '19 at 19:27