0

Here is what I am trying to do.

  1. I am introducing functionality to enable users to search for local restaurants.
  2. I created a HTTP cloud function, so that when the client delivers a keyword, the function will call an external API to search for the keyword, fetch the responses, and deliver the results.
  3. In doing #2, I need to make two separate url requests and merge the results.

When I checked, the function does call the API, fetch the results and merge them without any issue. However, for some reason, it only returns null to the client.

Below is the code: could someone take a look and advise me on where I went wrong?

        exports.restaurantSearch = functions.https.onCall((data,context)=>{
            const request = data.request;
            const k = encodeURIComponent(request);
            const url1 = "an_url_to_call_the_external_API"+k; 
            const url2 = "another_url_to_call_the_external_API"+k;
            const url_array = [ url1, url2 ];
            
            const result_array = [];
            const info_array = [];

            url_array.forEach(url=>{
                return fetch(url, {headers: {"Authorization": "API_KEY"}})
                .then(response=>{
                    return response.json()
                })
                .then(res=>{
                    result_array.push(res.documents);
                    if (result_array.length===2) {
                        const new_result_array_2 = [...new Set((result_array))];
                        new_result_array_2.forEach(nra=>{
                            info_array.push([nra.place_name,nra.address_name])
                        })
                        //info_array is not null at this point, but the below code only return null when checked from the client
                        return info_array;
                    }
                })
            .catch(error=>{
                console.log(error)
                return 'error';
            })
        })
        });

Thanks a lot in advance!

0

1 Answer 1

1

You should use Promise.all() instead of running each promise (fetch request) separately in a forEach loop. Also I don't see the function returning anything if result_array.length is not 2. I can see there are only 2 requests that you are making but it's good to handle all possible cases so try adding a return statement if the condition is not satisfied. Try refactoring your code to this (I've used an async function):

exports.restaurantSearch = functions.https.onCall(async (data, context) => {
  // Do note the async                            ^^^^^
  const request = data.request;
  const k = encodeURIComponent(request);
  const url1 = "an_url_to_call_the_external_API" + k;
  const url2 = "another_url_to_call_the_external_API" + k;
  const url_array = [url1, url2];

  const responses = await Promise.all(url_array.map((url) => fetch(url, { headers: { "Authorization": "API_KEY" } })))
  const responses_array = await Promise.all(responses.map((response) => response.json()))
  console.log(responses_array)
  const result_array: any[] = responses_array.map((res) => res.documents)

  // Although this if statement is redundant if you will be running exactly 2 promises
  if (result_array.length === 2) {
    const new_result_array_2 = [...new Set((result_array))];
    const info_array = new_result_array_2.map(({place_name, address_name}) => ({place_name, address_name}))
    return {data: info_array}
  }
  return {error: "Array length incorrect"}
});

If you'll be running 2 promises only, other option would be:

// Directly adding promises in Promise.all() instead of using map
const [res1, res2] = await Promise.all([fetch("url1"), fetch("url2")])
const [data1, data2] = await Promise.all([res1.json(), res2.json()])

Also check Fetch multiple links inside of forEach loop

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.