2

I have a variable I'm setting based on the result of an async function, the variable is initialState

const initialState = await getContacts()
  .then((body) => {
    console.log('body: ');
    console.log(body);
    return body;
  }).catch(err => console.log(err));

My getContacts() returns a promise that should be the result of this function:

export async function getContacts() {
  let data = fetch('/api/contacts').then((data) => {
    console.log(data);
    return data.json();
  }).catch(err => console.log(err));

  return data;
}

I think part of my problem might be that I'm trying to call this from a plain javascript file. It is actually the index.js of my React application. I'm fetching some sort of initial state of my app from the DB before I load up the app. I should move this code and clean it up quite a bit, but I was trying to get a quick and dirty test up and running. I'm getting a compiler error:

SyntaxError: \contacts\client\index.js: Can not use keyword 'await' outside an async function

My index.js that contains the await is this:

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import App from './components/app';
import reducers from './reducers';
import { composeWithDevTools } from 'redux-devtools-extension';
import { getContacts } from './server/api';

const initialState = await getContacts()
  .then((body) => {
    console.log('body: ');
    console.log(body);
    return body;
  }).catch(err => console.log(err));

console.log('initial state: ');
console.log(initialState);

const composeEnhancers = composeWithDevTools({});
ReactDOM.render(
  <Provider store={ createStore(reducers, initialState, composeEnhancers(
  )) }>
   <App />
  </Provider>
, document.querySelector('.container'));
intA
  • 2,513
  • 12
  • 41
  • 66
  • Is this related to your previous question? [why-is-my-function-returning-a-promise-and-not-an-object-from-my-db](https://stackoverflow.com/questions/55507439/why-is-my-function-returning-a-promise-and-not-an-object-from-my-db/55507900#55507900) – jtabuloc Apr 05 '19 at 02:41
  • You are using await while setting initialState which is wrong. As the error suggests, await can be used only inside async function. Check @doublesharp's answer below. Its legit. – Peter Apr 05 '19 at 02:43
  • @jtabuloc yep. But the problem before was that my backend endpoint was not working, there was an issue with my webpack dev server. – intA Apr 05 '19 at 02:57
  • @VishalGulati when I do that I get an `Uncaught ReferenceError: regeneratorRuntime is not defined` error. I think this is due to using async/await in React? At least that was what I found last time I ran into this issue. – intA Apr 05 '19 at 03:02
  • @intA Check this out: https://stackoverflow.com/a/33527883/5346095 – Peter Apr 05 '19 at 03:04

3 Answers3

4

Wrap the call to getContacts() in an async function - you also don't want to mix up async/await with .then(),

(async function() {
  const contacts = await getContacts();
  console.log('contacts', contacts);
})();
doublesharp
  • 26,888
  • 6
  • 52
  • 73
1

You are correct in your assumption that attempting to call the asynchronous getContacts() function with an await is part of the issue with your code. In order to make a call to a function like await getContacts(){} you need to have that code wrapped in an asynchronous function that is defined like:

async function wrapperFunction() {
    const contacts = await getContacts()
    console.log('body: ')
    console.log(contacts)
}

Also, if you want to execute this function and also add some error handling logic you can do this:

wrapperFunction().catch((error) => {
    console.log(error)
})

The contacts variable would then be your initial state as well to pass to your Redux store createStore() function call.

It is possible to mix the two since they are both syntaxes for handling asynchronous logic, but you just need to assemble usage of the two together properly. I suggest reading through the Mozilla documentation on async functions to get a good idea of how to use async/await as well as how you can use this convention with the Promise syntax as well.

Keith Dawson
  • 1,475
  • 16
  • 27
-2

You cant use await if not in an async function declaration.

Maybe this can work:

const initialState = async () => {
  try {
    await getContacts();
  } catch (err) {
    console.log(err)
  }
}
console.log('initial state: ');
console.log(initialState);

You are missing the point of async/await mixing it with .then()

You don't need then, because await returns a solved promise.

palafox_e
  • 85
  • 1
  • 8
  • I get a `index.js?1942:32 Uncaught ReferenceError: regeneratorRuntime is not defined` now. I believe this is due to using async/await in React, I tried a similar implementation before but couldn't get it to work in React with async/await. – intA Apr 05 '19 at 02:55
  • That is setting `initialState` to a `Promise` by assigning it to an `async` function. When you `console.log` it will not be the result of `getContacts()`, it will be the unresolved promise. – doublesharp Apr 05 '19 at 03:40