userMod2
userMod2

Reputation: 8960

Typescript - Using a value from then in function return block

I have this function:

function configureClient(): ApolloClient<ApolloCache<any>> {
    let myToken = getOktaToken().then(token => {
        return token
    });

    return new ApolloClient<InMemoryCache>({
        uri: "someUrl",
        cache: new InMemoryCache(),
        headers: {
            someAuth: myToken
        }
    });
}

I'm want someAuth: myToken in headers of the return block to be set however not sure how do this using this then block.

Also to add:

Generally, I would have done, let myToken = await getOktaToken() - however I'm unable to make the async function configureClient() as that ApolloClient<ApolloCache<any>> complains about some ES3. I presume this would have worked? Type 'typeof DefaultClient' in not a valid async function return type in ES5/ES3 because it does not refer to a Promise compatible constructor value

Upvotes: 0

Views: 1042

Answers (1)

Daniel Rearden
Daniel Rearden

Reputation: 84677

Promises are asynchronous -- the callback you pass to then is evaluated after your function returns. You can make the whole configureClient function return a Promise, but that will mean you will have to change how you're using it elsewhere in your app (again, because at that point, the whole client will be initialized asynchronously).

function configureClient(): Promise<ApolloClient<ApolloCache<any>>> {
  return getOktaToken().then(token => {
    return new ApolloClient<InMemoryCache>({
      uri: "someUrl",
      cache: new InMemoryCache(),
      headers: {
        someAuth: token
      }
    });
  });
}

// or the equivalent using async/await syntax

async function configureClient(): Promise<ApolloClient<ApolloCache<any>>> {
  const token = await getOktaToken()
  return new ApolloClient<InMemoryCache>({
    uri: "someUrl",
    cache: new InMemoryCache(),
    headers: {
      someAuth: token
    }
  });
}

You could delay rendering your app until the client is fetched. For example:



const App = () => {
  const [client, setClient] = useState(null)
  useEffect(() => {
    configureClient().then(setClient)
  }, [])

  if (!client) {
    return null
  }

  return (
    <ApolloProvider client={client}>
      ...
    </ApolloProvider>
  )
}

If you have headers that need to be fetched asynchronously, though, the preferred way to do so is using apollo-link-context. You should stop using Apollo Boost or better yet migrate to the latest Apollo Client. Then you can configure the links for your client instance and add a Context Link as shown here.

Upvotes: 2

Related Questions