Adrijana Radosevic
Adrijana Radosevic

Reputation: 1

How to avoid then() nesting with js promises?

I'm writing an endpoint which modifies caption in a firebase entry; then collects all Typesense entries related to the firebase entry and fixes them too.

My code works exactly as I'd want it to. But I ended up going one level deeper with the .then() nesting than I would have liked to, resulting in 2 .catch() statements instead of one.

It somehow feels this is formally wrong and I'd love to fix it, but I don't know how to get myself "out" of it.

db.collection('posts').doc(post.id)
  .update({
    caption: post.caption
  })
  .then((data) => {
    // tsense collect all with fireId
    let searchParameters = {
      q: '*',
      filter_by: `fireId:=${post.id}`
    }
    TsenseClient.collections(Collection).documents().search(searchParameters)
      .then((data) => {
        console.log(data);
        return data
      })
      .then((tsenses) => {
        // tsense update all with fireId
        let tsenseUpdates = []
        tsenses.hits.forEach((hit) => {
          let doc = {
            "caption": post.caption
          }
          tsenseUpdates.push(TsenseClient.collections(Collection).documents(hit.id).search(searchParameters))
        })
        return Promise.allSettled(tsenseUpdates)
      })
      .then((tsenseUpdates) => {
        response.send('Update done.')
      })
      .catch((err) => {
        console.log(err);
      })
  })
  .catch((err) => {
    console.log(err);
  })

Upvotes: 0

Views: 74

Answers (3)

mahmoud samir
mahmoud samir

Reputation: 1

consider using async await you can find the docs for the async function on the mdn => https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

async function foo() {
    const p1 = new Promise((resolve) => setTimeout(() => resolve('1'), 1000))   const p2 = new Promise((_,reject) => setTimeout(() => reject('2'), 500))
  const results = [await p1, await p2] // Do not do this! Use Promise.all or Promise.allSettled instead.}
foo().catch(() => {}) // Attempt to swallow all errors.

code snippet example img

Upvotes: 0

Ahmad Alfy
Ahmad Alfy

Reputation: 13371

Instead of using then on the TsenseClient promise, you should return the promise instead and it will then-able like the following:

db.collection('posts').doc(post.id)
  .update({
    caption: post.caption
  })
  .then((data) => {
    // tsense collect all with fireId
    let searchParameters = {
      q: '*',
      filter_by: `fireId:=${post.id}`
    }
    return TsenseClient.collections(Collection).documents().search(searchParameters)
  })
    .then((data) => {
      console.log(data);
      return data
    })
    .then((tsenses) => {
      // tsense update all with fireId
      let tsenseUpdates = []
      tsenses.hits.forEach((hit) => {
        let doc = {
          "caption": post.caption
        }
      tsenseUpdates.push(TsenseClient.collections(Collection).documents(hit.id).search(searchParameters))
      })
      return Promise.allSettled(tsenseUpdates)
    })
    .then((tsenseUpdates) => {
      response.send('Update done.')
    })
  .catch((err) => {
    console.log(err);
  })

Upvotes: 1

Krzysztof Safjanowski
Krzysztof Safjanowski

Reputation: 7438

Please focus on part

.then((data) => {
  // tsense collect all with fireId
  let searchParameters = {
    q: '*',
    filter_by: `fireId:=${post.id}`
  }
  TsenseClient.collections(Collection).documents().search(searchParameters)
  .then((data) => {
    console.log(data);
    return data
  }) 

and replace with:

.then((data) => {
  // tsense collect all with fireId
  let searchParameters = {
    q: '*',
    filter_by: `fireId:=${post.id}`
  }
  return TsenseClient.collections(Collection).documents().search(searchParameters)
})
.then((data) => {
  console.log(data);
  return data
}) 

You can read more about it https://medium.com/@justintulk/flattening-nested-promises-in-javascript

Upvotes: 2

Related Questions