0

I hope this question is not a duplicate, but I think so. I made a research before posting but the answers I found didn't help me.

I'm using Firebase to save a string content inside the key myKey so the structure is something like:

{ myKey: {
    key1: an object stringified,
    key2: an object stringified,
    key2: an object stringified,
    ...

  }
}

This is my code:

async fetchContent(documentId, sheetId) {
    const json = await this.fetchSheetContent(documentId, sheetId, 'A:B')

    const content = json.map(async (row) => {
        const stringifiedContent = await readValue(new URL(row.URL).search) // obtain `an object stringified`
        const parsedContent = JSON.parse(stringifiedContent)
        return { row, parsedContent }
      }
    )

    console.log(content) // <-- content is a pending Promise, I want instead an array of objects
    
    // do something with the array of objects
    // return content.map(c => {...) 
}

async function readValue(search) {
  const queryParams = new URLSearchParams(search)
  const key = queryParams.get('myKey')
  if (!key) return
  const stringifiedState = await createSyncContent(STATE_KEY).get(key)
  return stringifiedContent
}

const createSyncContent = (db) => {
  const ref = fbDb.database().ref(db)

  const syncContent = {
    get: async (key) => {
      try {
        const snapshot = await ref.child(key).get()
        if (snapshot.exists()) {
          const value = snapshot.val()['myKey']
          return value
        } else {
          console.log('ERROR')
        }
      } catch (error) {
        console.error(error)
      }
    },
  }
  return syncContent
}

In that code content is a pending Promise, I want instead an array of objects. Where is the error?

Thanks a lot, I'm a beginner in Promises.


I tried Promise.all:

async fetchContent(documentId, sheetId) {
    const json = await this.fetchSheetContent(documentId, sheetId, 'A:B')

    const content = Promise.all(json.map(async (row) => {
        const stringifiedContent = await readValue(new URL(row.URL).search)
        const parsedContent = JSON.parse(stringifiedContent)
        return { row, parsedContent }
      }
    ))
    
    // do something with the array of objects
    // return content.map(c => {...)
}

and:

async fetchContent(documentId, sheetId) {
    const json = await this.fetchSheetContent(documentId, sheetId, 'A:B')

    const content = await json.map(async (row) => {
        const stringifiedContent = await readValue(new URL(row.URL).search)
        const parsedContent = JSON.parse(stringifiedContent)
        return { row, parsedContent }
      }
    )
    
    // do something with the array of objects
    // return content.map(c => {...)
}

It seems not to work.

whitecircle
  • 237
  • 9
  • 34

2 Answers2

0

You missing await. Try this:

const content = await json.map(async (row) => {...})
console.log(content)
ulou
  • 5,542
  • 5
  • 37
  • 47
0

As far as I understand JS, when you use async before a function, the return type of the function changes to a promise.

Whats Wrong:

    const content = json.map(async (row) => {
        const stringifiedContent = await readValue(new URL(row.URL).search) // obtain `an object stringified`
        const parsedContent = JSON.parse(stringifiedContent)
        return { row, parsedContent }
      }
    )

Here you are using async before map callback function thus the map returns array of pending promises which you see in content.

Solution (Can be many) :

You can use Promise.all to run multiple api requests in parallel and wait until all of them are resolved.

Drawback: It will fail if any of the promise fails to resolve.

Workaround: This answer

For Reference : Promise.all

I haven’t tested the answer above. You can try that as well since its short and easy.

Abhishek Sharma
  • 2,485
  • 1
  • 21
  • 35