Firebase 云函数:http 函数 returns 空

Firebase cloud function: http function returns null

这是我正在尝试做的事情。

  1. 我正在引入使用户能够搜索当地餐馆的功能。
  2. 我创建了一个 HTTP 云函数,这样当客户端传递关键字时,该函数将调用外部 API 来搜索关键字、获取响应并传递结果。
  3. 在执行 #2 时,我需要发出两个单独的 url 请求并合并结果。

当我检查时,该函数确实调用了 API,获取结果并毫无问题地合并它们。但是,由于某种原因,它对客户端仅 returns null。

下面是代码:有人可以看看我哪里出错了并告诉我吗?

        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';
            })
        })
        });

提前致谢!

你应该使用 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"}
});

如果您只 运行 2 个承诺,其他选项将是:

// 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()])

同时勾选