服务器操作未间歇运行

🌐

本帖由 DeepL 翻译。如有任何翻译错误,请告知我们!

问题所在

当我在服务器端运行以下 Mixpanel 跟踪代码时,只能断断续续地记录事件。

mixpanel.track(event, { distinct_id: userId, properties }, err => {
  if (err) {
    reject(err);
  } else {
    resolve("success");
  }
});

在本地环境中,所有事件都被正确记录,但在 Vercel 部署中,只有部分事件被记录。

原因

在了解原因之前,我们先来了解一下 Vercel 功能。Vercel 为部署在 Vercel 上的环境提供了一种名为 Vercel Function的功能。

简而言之,Vercel Function 就是部署在 Vercel 上的所有服务器端代码都在 Vercel 的基础架构下运行,这意味着它是FaaS

FaaS 是 "功能即服务"(Function as a Service)的缩写,是实现无服务器计算的方法之一。其理念是,功能是我们在开发中使用的函数,我们把它们放在云服务上,只有在需要时才调用它们。 换句话说,FaaS 允许我们编写和执行函数,而无需开发服务器。 得益于 Vercel 的这一功能,我们可以使用 API Routes、SSR 等,而无需架设服务器。

✏️了解更多 Vercel 的无服务器架构由 AWS 上的 Lambda 提供支持。

导致问题的代码也被设置为Server Action并在服务器上执行,由于 Vercel 基于无服务器,因此代码被注册为无服务器函数。

但是,无服务器函数有可能执行过程中终止进程,在这种情况下,函数可能在异步操作完成之前就终止了,这意味着回调函数没有执行,事件也没有正确发送。

解决方法

我们将代码封装在一个 Promise 中,如下所示,所有事件都能正确发送。

return new Promise((resolve, reject) => {
    mixpanel.track(event, { distinct_id: userId, properties }, (err) => {
      if (err) {
        reject(err)
      } else {
        resolve('success')
      }
    })
  })

为什么要在服务器端运行跟踪代码?

那我们为什么不在客户端运行类似 mixpanel.track 这样的跟踪代码呢?

  • 数据完整性:当事件直接从客户端发送时,它们可能会因用户浏览器设置(如广告拦截器)或网络问题而被遗漏。在服务器端运行可减少这些外部因素的影响,使数据收集更加可靠。
  • 与业务逻辑集成:当跟踪事件与服务器端逻辑(如支付处理、用户身份验证等)密切相关时,直接在服务器上进行处理会更自然、更高效。例如,如果您想在支付完成后记录一个事件,那么在服务器上检查支付是否成功,然后再进行跟踪就比较合理。
  • 优化性能:在客户端处理跟踪请求会导致额外的网络调用,从而增加页面加载时间。在服务器端处理可减轻客户端的负担,改善用户体验。

因此,尽可能在服务器端而不是客户端运行,可以获得更准确、更可靠的指标。

🔎 另请参见