0

I build a PWA. On Server-Side-Rendering I want to wait for the responses to build and deliver the HTML-document with data the API returns. On client I do not have to wait for the responses, since the client is allowed to render a loading animation for example.

Therefore I want the following await to be conditional. On the Server is should like this:

await Promise.all([
  store.dispatch(fetchUser()),
  store.dispatch(fetchFriends()),
  store.dispatch(fetchPosts())
])

On client the execution should look like this

Promise.all([
  store.dispatch(fetchUser()),
  store.dispatch(fetchFriends()),
  store.dispatch(fetchPosts())
])

I am looking for a wrapper function that appends the await on the server. I do not want to have duplicated code at every occurrences like this:

if (isServer) {
  await Promise.all([
    store.dispatch(fetchUser()),
    store.dispatch(fetchFriends()),
    store.dispatch(fetchPosts())
  ]);
} else {
  Promise.all([
    store.dispatch(fetchUser()),
    store.dispatch(fetchFriends()),
    store.dispatch(fetchPosts())
  ])
}

Edit: I tried this but the await does not work on server side.

export default async function ssrAwait(promise): Promise<any> {
  if (isServer) {
    return await promise;
  } else {
    return promise;
  }
}

ssrAwait(Promise.all([
  store.dispatch(fetchUser()),
  store.dispatch(fetchFriends()),
  store.dispatch(fetchPosts())
]))

Any suggestions on this?

tomole
  • 927
  • 3
  • 12
  • 35
  • I suggest you create a single method or variable and utilize it throughout your code wherever it is needed. – Zubair Saif Jan 11 '23 at 10:27
  • 1
    Just put the duplicated expression in a variable? – Bergi Jan 11 '23 at 10:27
  • Are you using NgRx or Redux? – Richard Dunn Jan 11 '23 at 11:21
  • Redux (redux-toolkit) – tomole Jan 11 '23 at 11:23
  • Oh, I see. You can't await an action, they're fire and forget. You have to track the state yourself. So if you're looking to block until the data has loaded, you need to explicitly track this in the store with a reducer, "loading", "loaded", "errored", etc. See [this answer](https://stackoverflow.com/a/55683451/4632627) for a clearer idea. In short, you'll need to subscribe to the selector and wait for the correct state, and you'll have to set that state yourself before/after the ajax calls. Tedious, I know... – Richard Dunn Jan 11 '23 at 11:29
  • `return` and `return await` [usually behave the same](https://stackoverflow.com/questions/38708550/difference-between-return-await-promise-and-return-promise). – Ivar Jan 11 '23 at 11:30
  • Regarding your last edit with `ssrAwait`: This doesn't make any difference: Because if you don't `await ssrAwait(...)` nothing is awaited, and if you do `await ssrAwait` it doesn't matter wheter you await the promise inside the function or outside of it. – derpirscher Jan 12 '23 at 13:08

1 Answers1

0

Promise.all returns a promise so you could simply do

let pa = Promise.all([...]);
if (server) await pa;
derpirscher
  • 14,418
  • 3
  • 18
  • 35