Ae Leung
Ae Leung

Reputation: 378

How to add await inside Promise?

Is it possible to add Await inside new promise ?

Originally, I don't need to put a await before making any request to the server. But one day, the server requires every request to have a token before sending out.

Let's take an example of the code

export const countries = (data: IData) => {
  const countryRequests = getRequests(data)
  const countryResponse = countryRequests?.reduce((countryResponse, request) => {
    const countryResponses = new Promise((resolve, reject) => {
      instance
        .post(`/country`, request)
        .then(data => {
          resolve(data)
        })
        .catch(err => {
          reject(err)
        })
    })

    return [...countryResponse, countryResponses]
  }, [])


  return countryResponse
}

new code( putting async into the callback of promise):

export const countries = (data: IData) => {
  const countryRequests = getRequests(data)
  const countryResponse = countryRequests?.reduce((countryResponse, request) => {
    const countryResponses = new Promise(async (resolve, reject) => { //add async here
    await addAccessToken() // add header into token before sending the requests
      instance
        .post(`/country`, request)
        .then(data => {
          resolve(data)
        })
        .catch(err => {
          reject(err)
        })
    })

    return [...countryResponse, countryResponses]
  }, [])


  return countryResponse
}

addToken function:

export const addAccessToken = async () => {
  const accessToken = await instance.get<IAccessToken>(
    '/access_token'
  )
  const { access_token } = accessToken.data
  instance.defaults.headers.common['Authorization'] = `Be ${access_token}`
}

But then I got a error below

Promise executor functions should not be async.(no-async-promise-executor)

How can I get rid of the error?

-------------- new changes---------

export const countries = async (data: IData) => {
  const countryRequests = getRequests(data)
  await addAccessToken()

  const countryResponse = countryRequests?.reduce((countryResponse, request) => {
    const countryResponses = instance
      .post(`/country`, request)  //------- May I ask, if it is successful call, then this will autmactically equvlanet to calling resolve (data) in my previosu code? 
      .catch(err => {
        console.error(err)
      })
    return [...countryResponse, countryResponses]
  }, [])

 
  return countryResponse
}

added new prmosie.all part

const countryResponses = countries(data)

    //set content for api 1
    Promise.all([...countryResponses])
      .then(values => {
        const countryResponsesResult = values.map((value, _index) => {
          return value.data.result ? value.data.result : []
        })
       
        //Set content for api 1
        props.setProjection({
          kind: 'success',
          payload: {
            data: countryResponsesResult,
          },
        })
      })
      .catch(_error => {
        //Set content for api 1
        props.setProjection({
          kind: 'fail',
          payload: {
            error: new Error(_error.message),
          },
        })
      })

Upvotes: 0

Views: 127

Answers (2)

Ae Leung
Ae Leung

Reputation: 378

Somehow I found this work.

export const countries = (data: IData)=> {
  const countryRequests  = getRequests(data)
  const countryResponse  = countryRequests?.reduce((countryResponse, request) => {
    // return promise
    const countryResponses  = new Promise((resolve, reject) => {
      addAccessToken().then(()=>{
        instance
          .post(`/country`, request)
          .then(data => {
            // change the returned propmise state into resolved
            resolve(data)
          })
          .catch(err => {
            reject(err)
          })
      })

    })
  //return the whole set of simlationCalls promise. When all promise is resolved, promise all will be notified and excute whatever it needs to execute
    return [...countryResponse, countryResponses]
  }, [])

  return countryResponse
}

Upvotes: 1

Marios
Marios

Reputation: 328

As @deceze mentioned, instance already returns a promise for you so no need to return your own promise.

Just

export const countries = async (data: IData) => {

await addAccessToken()
const countryResponses = await instance.post(`/country`, request)
//your code//

If you don't want to use await and use promises and then instead you should have something like the below(promise chaining):

export const countries = (data: IData) => {

addAccessToken()
     .then((data)=>{
        const countryResponses = instance.post(`/country`, 
        request)
     })
     .then(//your code//)

Upvotes: 2

Related Questions