How to make Nextjs not return props before getStaticProps has completed all requests (Promises)?

Asked

Viewed 9 times

-1

Within the function getStaticProps I take some data from the database and perform in them some treatments to suit the way I will use them. Everything happens exactly as it should, except that javascript is not waiting for the resolution of a file.

await realtime
    .ref( '/produtos/' )
    .once( 'value', async ( snapshot ) => {
      // pega todos os dados do arquivo produto se existir

      if ( snapshot.exists() ) {
        // ... Realizo aqui algumas transformações no formato dos dados ... //
        // ...

        const vetPromise = await criarArrayDePromisesDasImagens( produtos )

        produtos = await Promise.all( vetPromise ).then( ( values ) => { // resolve todas as promisses e então coloca o resultado das imagens no produto
          // Pega url atual da imagem no Firestore e armazena no mesmo local que antes tinha apenas uma url estatica do google, "gs://..."
          const result = porAsImagensNosProdutos( values, produtos )
          return result
        } )
      } else console.log( 'Dados não existentes' )
    } )

By calling await Promise.all() the block of this block hangs here while the file is not solved, however at that time the execution leaves the callback of the realtime.ref().once() and goes back to the scope of getStaticProps and therefore returns my props without Promise having returned the correct data, goes with the static data of the firestore image and not with the url received by the method pegarImagem() which has the following instructions:

let refUrl = refFromURL('gs://...')
let url = refUrl.getDownloadURL()

My getStaticProps is that way:

async function criarArrayDePromisesDasImagens( produtos ) : Promise<Promise<string>[]> {
  //...
  async function criarArrayDePromisesDasImagens( produtos ) : Promise<Promise<string>[]> {
      const promisses = []

      produtos.forEach( ( produto ) => {
        produto.item.forEach( async ( value ) => {
          const keyItem = Object.keys( value )[ 0 ]
          const imagem = value[ keyItem ].images[ 0 ]
          const urlRef = storage.refFromURL( imagem )
          const url = pegarImagem( urlRef ) // url recebe uma promisse pendente
          promisses.push( url ) // adiciona uma promisse ao vetor
        } )
    } )
    return promisses // retorna um vetor de promisses
  }

  // Nessa função todas as imagens recebidas dentro do vetor são retornadas ao seu local de origem
  function porAsImagensNosProdutos( vetpromisses: Array<string>, arrayProdutos: ProdutosType ) {
    const value = arrayProdutos
    const aux = 0
    value.forEach( ( produto, indexProduto ) => {
      produto.item.forEach( async ( itemValue, keyValue ) => {
        const keyItem = Object.keys( itemValue )[ 0 ]
        value[ indexProduto ].item[ keyValue ][ keyItem ].images[ 0 ] = vetpromisses[ aux ]
        // produtos[0].item[0]["-MhxS6SS7yWaysPCATX2"].images[0] = "url da imagem"
      } )
    } )
    return value
  }

    // Parte do codigo do realtime que foi mostrado anteriormente
    // await realtime.ref( '/produtos/' ).once( 'value', async ( snapshot ) => { ... }

  return {
    props: {
      produtos,
    }, // will be passed to the page component as props
  }
}

1 answer

0

Well, after a good night’s sleep waking up every 30 minutes with the same question in mind, I decided to return use the firebase callback just to process the data and did the part of rescuing the images out of this callback. At first it solves the problem of returning props before Promises are solved, but I still don’t know why async/await have not functioned as I would like. From what I understand, the block await realtime.ref().onde('value', async snapshot => {...} ) does not wait for all languages to resolve and the code continues to run on the line immediately after that block, return {props}.
Although I don’t quite understand what happened, this was my solution to the problem:

// após o calback da função once do firebase, quero que todas as url estaticas do google sejam tranformadas em urls do dominio firebasestorage.googleapis.com
  try {
    // Pega url atual da imagem no Firestore e armazena no mesmo local que antes tinha apenas uma url estatica do google, "gs://..."
    console.log( 'Veio até aqui' )
    const vetPromise = await criarArrayDePromisesDasImagens( produtos )

    produtos = await Promise.all( vetPromise ).then( ( values ) => { // resolve todas as promisses e então coloca o resultado das imagens no produto
      const result = porAsImagensNosProdutos( values, produtos )
      console.log( 'Imagens resgatadas, promise sucess' )
      return result
    } )
    console.log( 'produtos promise all =>', JSON.stringify( produtos, null, 4 ) )
  } catch ( error ) {
    global.console.log( 'erro ao capturar promises => ', error )
  }

Browser other questions tagged

You are not signed in. Login or sign up in order to post.