typescript 超级数据库边缘函数运行两次,但只调用一次

xoefb8l8  于 2023-03-13  发布在  TypeScript
关注(0)|答案(1)|浏览(122)

我在Supabase的typescript中有一个相对简单的边缘函数,它连接到我们的postgres数据库并运行查询。该函数通过一个html按钮调用。当在cli中本地运行或通过生产运行时,一旦部署,这两种情况下,边缘函数都会运行两次。查询运行两次,但控制台日志显示整个函数运行两次。然而,在浏览器控制台日志只显示一个调用的按钮点击函数。有什么想法?
下面是html:

<html>
  <head>
    <meta charset="utf-8">
    <title>Invoke Supabase Function</title>
  </head>
  <body>
    <button id="invoke-button">Invoke Function</button>
    <script language="Javascript">
      const apiKey = XXXXX
      const functionEndPoint = 'http://localhost:54321/functions/v1/';

      const inputData = { name: 'Blah' };
      
      const invokeFunction = () => {
        console.log('Called invokeFunction');
        fetch(`${functionEndPoint}`, {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${apiKey}`
          },
          body: JSON.stringify(inputData)
        })
          .then(response => response.json())
          .then(data => {            
            console.log(data);
          })
          .catch(error => {
            console.error(error);
          });
      };
      
      document.getElementById('invoke-button').addEventListener('click', invokeFunction);
    </script>
  </body>
</html>

函数如下:

import * as postgres from 'https://deno.land/x/postgres@v0.14.2/mod.ts'
import { serve } from 'https://deno.land/std@0.177.0/http/server.ts'
import { createClient } from 'https://esm.sh/@supabase/supabase-js@1.33.1'
import { corsHeaders } from '../_shared/cors.ts'

const databaseUrl = "postgresql://XXXXX"
const pool = new postgres.Pool(databaseUrl, 3, true)

serve(async (_req) => {
  
  
  try {
    // Grab a connection from the pool
    const connection = await pool.connect()

    try {
      // Run a query (its actually a non-deterministic fb function/stored proc)
      console.log("inbound startgame request...")
      const result = await connection.queryObject`SELECT public."newGame"();`
      const rr = result.rows
      console.log(rr)

      // Encode the result as pretty printed JSON
      const body = JSON.stringify(
        rr,
        (key, value) => (typeof value === 'bigint' ? value.toString() : value),
        2
      )

      // Return the response with the correct content type header
      return new Response(
        JSON.stringify(rr),
        { 
          headers: { ...corsHeaders, "Content-Type": "application/json" },
          status: 200,
        },
      )

    } finally {
      // Release the connection back into the pool
      connection.release()
    }
  } catch (err) {
    console.error(err)
    return new Response(String(err?.message ?? err), { status: 500 })
  }
5f0d552i

5f0d552i1#

Eureka 了!边缘函数需要这个:

if (req.method === 'OPTIONS') {
    return new Response('ok', { headers: corsHeaders })
  }

显然,浏览器会向该函数发送一个预检请求,以查看它是否支持COR。如果您没有正确处理这个问题,侦听函数将在预检期间正常运行,然后在主调用期间再次正常运行。由于上面的代码返回了COR头,因此这两次运行在浏览器上都是成功的。

相关问题