简体   繁体   English

Firebase 云 function: http function 返回 null

[英]Firebase cloud function: http function returns null

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.我创建了一个HTTP云function,这样客户端下发关键词时,function会调用外部API搜索关键词,获取响应,下发结果。
  3. In doing #2, I need to make two separate url requests and merge the results.在执行 #2 时,我需要发出两个单独的 url 请求并合并结果。

When I checked, the function does call the API, fetch the results and merge them without any issue.当我检查时,function 确实调用了 API,获取结果并毫无问题地合并它们。 However, for some reason, it only returns null to the client.但是,由于某种原因,它只向客户端返回 null。

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!非常感谢!

You should use Promise.all() instead of running each promise (fetch request) separately in a forEach loop.您应该使用Promise.all()而不是在forEach循环中单独运行每个 promise (获取请求)。 Also I don't see the function returning anything if result_array.length is not 2 .如果result_array.length不是2 ,我也看不到 function 返回任何内容。 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.我可以看到您只提出了 2 个请求,但最好处理所有可能的情况,因此如果不满足条件,请尝试添加返回语句。 Try refactoring your code to this (I've used an async function ):尝试将您的代码重构为此(我使用了异步 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:如果您只运行 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()])

Also check Fetch multiple links inside of forEach loop还要检查Fetch multiple links inside forEach loop

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM