搜索
首页web前端js教程使用 React 和 Supabase 构建自定义调度程序

介绍

调度是现代应用程序的关键功能之一。它可以使我们能够运行可以自动化的定期任务。诸如发送提醒、安排帖子、更新数据或自动化工作流程等任务。

因此,在本文中,我们将构建一个调度程序来在 dev.to 上发布文章。虽然 dev.to 具有调度功能,但我们将以我们的方式实现它们,这可用于构建任何类型的调度程序应用程序。

那么,让我们开始吧。

技术堆栈

我们将使用以下技术堆栈:

  • React: 我们将使用 React,特别是 ViteJS 和 React 来构建前端。
  • Supabase:它为构建应用程序提供了一体化的解决方案。它提供数据库、身份验证、存储、边缘功能等等。我们将使用 Supbase 中的以下内容:
    • 数据库:用于存储文章信息和排程时间。
    • Cron Job:用于定期运行以调用 Edge 函数
    • 边缘功能:这将检查是否有任何文章的当前时间与预定时间相同。如果那样它就会发布这篇文章。

这足以轻松构建调度程序应用程序。

处理应用程序

让我们讨论一下应用程序是如何工作的,这使得理解应用程序的流程变得很容易。以下是流程一一:

  1. 通过前端添加文章到数据库。
  2. Cron 作业将每分钟运行一次以调用边缘函数。
  3. 将执行边缘函数来检查当前时间是否与预定文章一致。如果有文章就会发布文章。
  4. post表中的文章数据将会更新。 # 构建前端

随着大量生成式人工智能的出现,建筑前端最近变得安静。我们将要使用的人工智能之一是 Bolt.new。为什么是螺栓.new?它可以生成具有依赖项和所有配置(例如 tailwindcss)的完整 React 应用程序。您可以使用 StackBlitz 直接编辑文章并部署应用程序。如果需要,可以下载代码在本地运行。额外的一点是它与 Supabase 集成得很好,因此您可以通过 Supbase 集成生成一个工作的 React 应用程序。

我用它来生成正面。这是所有页面。

应用程序.tsx

这将处理用于显示组件并提供登陆页面的页面。

    function App() {
      const [posts, setPosts] = useState<scheduledpost>([]);
      const handleSchedulePost = async (data: CreatePostData) => {
        // In a real app, this would make an API call to your edge function
        const newPost: ScheduledPost = {
          content: data.content,
          scheduled_time: data.scheduledTime,
          status: 'pending',
          title: data.title,
          tags: data.tags
        };
        const { error } = await supabase
      .from('scheduled_posts')
      .insert(newPost)
      if (error){
        alert(`Erorr: ${error}`)
        return
      }
        // setPosts((prev) => [...prev, newPost]);
      };
      const fetchScheduedPost = async () => {
        const { data, error } = await supabase
      .from('scheduled_posts')
      .select()
      if(error){
        alert(`Erorr Fetching Data: ${error}`)
        return
      }
      setPosts(data)
      } 
      useEffect(() => {
        fetchScheduedPost()
      },[])
      return (
        <div classname="min-h-screen bg-gray-50">
          <header classname="bg-white shadow-sm">
            <div classname="max-w-4xl mx-auto px-4 py-4">
              <div classname="flex items-center gap-2">
                <newspaper classname="h-8 w-8 text-blue-500"></newspaper>
                <h1 id="Dev-to-Post-Scheduler">Dev.to Post Scheduler</h1>
              </div>
            </div>
          </header>
          <main classname="max-w-4xl mx-auto px-4 py-8">
            <div classname="grid gap-8 md:grid-cols-2">
              <div>
                <h2 id="Schedule-New-Post">Schedule New Post</h2>
                <postform onsubmit="{handleSchedulePost}"></postform>
              </div>
              <div>
                <scheduledposts posts="{posts}"></scheduledposts>
              </div>
            </div>
          </main>
        </div>
      );
    }
    export default App;
</scheduledpost>

SchudledPost.tsx

这会显示预定的文章。

    const StatusIcon = ({ status }: { status: ScheduledPost['status'] }) => {
      switch (status) {
        case 'posted':
          return <checkcircle classname="h-5 w-5 text-green-500"></checkcircle>;
        case 'failed':
          return <xcircle classname="h-5 w-5 text-red-500"></xcircle>;
        default:
          return <clock3 classname="h-5 w-5 text-yellow-500"></clock3>;
      }
    };
    export function ScheduledPosts({ posts }: ScheduledPostsProps) {
      return (
        <div classname="space-y-4">
          <h2 id="Scheduled-Posts">Scheduled Posts</h2>
          {posts.length === 0 ? (
            <p classname="text-gray-500 text-center py-8">No scheduled posts yet</p>
          ) : (
            <div classname="space-y-4">
              {posts.map((post, index) => (
                <div key="{index}" classname="bg-white p-4 rounded-lg shadow-md border border-gray-100">
                  <div classname="flex items-start justify-between">
                    <div classname="flex-1">
                      <p classname="text-gray-800 mb-2">{post.title}</p>
                      <div classname="flex items-center gap-4 text-sm text-gray-500">
                        <div classname="flex items-center gap-1">
                          <calendar classname="h-4 w-4"></calendar>
                          {new Date(post.scheduled_time).toLocaleDateString()}
                        </div>
                        <div classname="flex items-center gap-1">
                          <clock classname="h-4 w-4"></clock>
                          {new Date(post.scheduled_time).toLocaleTimeString()}
                        </div>
                      </div>
                    </div>
                    <statusicon status="{post.status}"></statusicon>
                  </div>
                </div>
              ))}
            </div>
          )}
        </div>
      );
    }

PostForm.tsx

这将处理用户可以提供有关文章的信息的表单。

    function App() {
      const [posts, setPosts] = useState<scheduledpost>([]);
      const handleSchedulePost = async (data: CreatePostData) => {
        // In a real app, this would make an API call to your edge function
        const newPost: ScheduledPost = {
          content: data.content,
          scheduled_time: data.scheduledTime,
          status: 'pending',
          title: data.title,
          tags: data.tags
        };
        const { error } = await supabase
      .from('scheduled_posts')
      .insert(newPost)
      if (error){
        alert(`Erorr: ${error}`)
        return
      }
        // setPosts((prev) => [...prev, newPost]);
      };
      const fetchScheduedPost = async () => {
        const { data, error } = await supabase
      .from('scheduled_posts')
      .select()
      if(error){
        alert(`Erorr Fetching Data: ${error}`)
        return
      }
      setPosts(data)
      } 
      useEffect(() => {
        fetchScheduedPost()
      },[])
      return (
        <div classname="min-h-screen bg-gray-50">
          <header classname="bg-white shadow-sm">
            <div classname="max-w-4xl mx-auto px-4 py-4">
              <div classname="flex items-center gap-2">
                <newspaper classname="h-8 w-8 text-blue-500"></newspaper>
                <h1 id="Dev-to-Post-Scheduler">Dev.to Post Scheduler</h1>
              </div>
            </div>
          </header>
          <main classname="max-w-4xl mx-auto px-4 py-8">
            <div classname="grid gap-8 md:grid-cols-2">
              <div>
                <h2 id="Schedule-New-Post">Schedule New Post</h2>
                <postform onsubmit="{handleSchedulePost}"></postform>
              </div>
              <div>
                <scheduledposts posts="{posts}"></scheduledposts>
              </div>
            </div>
          </main>
        </div>
      );
    }
    export default App;
</scheduledpost>

边缘功能

边缘函数是服务器端 TypeScript 函数,分布在全球边缘(靠近用户)。它们可用于监听 Webhook 或将您的 Supabase 项目与 Stripe 等第三方集成。边缘函数是使用 Deno 开发的。

要在本地运行和部署边缘函数,您需要具备以下条件:

  • Supbase CLI:您可以使用本指南在本地安装 CLI。只需使用 npm 和 npx 就很简单。
  • Docker 桌面:从这里安装 docker 桌面。

因此,安装后,您可以使用前端代码目录或其他目录来创建 Supabase Edge Function。

运行以下命令来启动一个supabase项目:

    const StatusIcon = ({ status }: { status: ScheduledPost['status'] }) => {
      switch (status) {
        case 'posted':
          return <checkcircle classname="h-5 w-5 text-green-500"></checkcircle>;
        case 'failed':
          return <xcircle classname="h-5 w-5 text-red-500"></xcircle>;
        default:
          return <clock3 classname="h-5 w-5 text-yellow-500"></clock3>;
      }
    };
    export function ScheduledPosts({ posts }: ScheduledPostsProps) {
      return (
        <div classname="space-y-4">
          <h2 id="Scheduled-Posts">Scheduled Posts</h2>
          {posts.length === 0 ? (
            <p classname="text-gray-500 text-center py-8">No scheduled posts yet</p>
          ) : (
            <div classname="space-y-4">
              {posts.map((post, index) => (
                <div key="{index}" classname="bg-white p-4 rounded-lg shadow-md border border-gray-100">
                  <div classname="flex items-start justify-between">
                    <div classname="flex-1">
                      <p classname="text-gray-800 mb-2">{post.title}</p>
                      <div classname="flex items-center gap-4 text-sm text-gray-500">
                        <div classname="flex items-center gap-1">
                          <calendar classname="h-4 w-4"></calendar>
                          {new Date(post.scheduled_time).toLocaleDateString()}
                        </div>
                        <div classname="flex items-center gap-1">
                          <clock classname="h-4 w-4"></clock>
                          {new Date(post.scheduled_time).toLocaleTimeString()}
                        </div>
                      </div>
                    </div>
                    <statusicon status="{post.status}"></statusicon>
                  </div>
                </div>
              ))}
            </div>
          )}
        </div>
      );
    }

以下命令可用于创建边缘函数

    export function PostForm({ onSubmit }: PostFormProps) {
      const [content, setContent] = useState('');
      const [title, setTitle] = useState('');
      const [tags, setTags] = useState<string>(['javascript', 'react']);
      const [scheduledTime, setScheduledTime] = useState('');
      const handleSubmit = async (e: React.FormEvent) => {
        e.preventDefault();
        onSubmit({ content, title, scheduledTime, tags });
        setContent('');
        setTitle('');
        setScheduledTime('');
        setTags([]);
      };
      const handleTagChange = (e: React.ChangeEvent<htmlselectelement>) => {
        const selectedOptions = Array.from(e.target.selectedOptions);
        const selectedTags = selectedOptions.map(option => option.value);
        if(tags.length {
          const newTags = selectedTags.filter(tag => !prevTags.includes(tag));
          return [...prevTags, ...newTags];
        });
        }

      };
      const removeTag = (tagToRemove: string) => {
        setTags(tags.filter(tag => tag !== tagToRemove));
      };
      return (
        <form onsubmit="{handleSubmit}" classname="space-y-4 bg-white p-6 rounded-lg shadow-md">
          <div>
            <label htmlfor="title" classname="block text-sm font-medium text-gray-700 mb-2">
              Post Title
            </label>
            <input type="text">



<p>I will provide the whole code as a GitHub repository at the end. </p>

<p>Now, let’s look at Supbase Integration.</p>

<h2>
  
  
  Supabase
</h2>

<p>First create an account on supabase, if you don’t have one. You can look at this article to get information about the creating an account on Supbase, Using ChatGPT with Your Own Data using LangChain and Supabase.</p>

<p>Create the table scheduled_post. You can use the below SQL code to run in the SQL Editor to create the table or you can create the table with Table Editor.<br>
</p>

<pre class="brush:php;toolbar:false">    create table
      public.scheduled_posts (
        id serial not null,
        content text not null,
        scheduled_time timestamp with time zone not null,
        status text null default 'pending'::text,
        created_at timestamp without time zone null default now(),
        title character varying null,
        devto_article_id character varying null,
        posted_at character varying null,
        tags character varying[] null,
        error_message character varying null,
        constraint scheduled_posts_pkey primary key (id)
      ) tablespace pg_default;
    create index if not exists idx_scheduled_time_status on public.scheduled_posts using btree (scheduled_time, status) tablespace pg_default;

上面的命令将在supabase中创建一个目录functions/xscheduler。在那里你可以找到index.ts。边缘函数使用 Deno 环境。

以下代码用于边缘函数:

    npx supabase init

对于 SUPABASE_URL 和 SUPABASE_SERVICE_ROLE_KEY 等 ENV,您将自动可用。对于DEVTO_ACCESS_TOKEN,您可以从这里生成它,然后进入项目设置→边缘功能添加令牌。该代币将在 Deno 环境中可用。

您可以使用这个指南来部署所需的边缘函数。

计划任务

Supbase 最近更新了 Cron 作业功能。现在,您可以使用仪表板创建玉米作业,之前您必须为此编写代码。您可以创建一个可以运行以下命令的作业:

  • SQL 片段
  • 数据库功能
  • HTTP 请求
  • Subase 边缘函数

我们将使用 Edge Function,您可以使用 Anon 密钥作为 Bearer Token 添加 Edge 函数的详细信息,例如名称和授权。

Building a Custom Scheduler Using React and Supabase

应用程序的工作

现在,我们已经创建了应用程序,让我们看看现在的工作情况。使用以下命令运行前端:

    supabase functions new xscheduler

Building a Custom Scheduler Using React and Supabase

添加标题、内容、时间和标签等详细信息。添加后,单击安排帖子。一旦文章的计划时间与当前时间匹配,cron 作业就会每分钟运行一次。将会发布。

当时间范围匹配时,文章将发布在 dev.to 上。

Building a Custom Scheduler Using React and Supabase

附加功能

使用上述技术,您可以为 X、Instagram、LinkedIn 等任何内容构建调度程序应用程序。您可以对其进行处理并添加如下功能:

  • 图像:使用supabase存储上传和获取缩略图图像。
  • 从 SQL 调用边缘函数:您可以通过从 SQL 片段或数据库函数调用边缘函数来提高效率。这样,只有当文章与当前时间匹配时,才会调用边缘函数。

您可以在 GitHub 上查看该项目的代码。

结论

创建调度程序应用程序可以简化发布文章、发送提醒和管理工作流程等自动化任务。使用 React 作为前端,Supabase 作为后端,我们构建了一个利用数据库、cron 作业和边缘功能的可扩展解决方案。这种方法可以适应各种用例,从而实现高效的自动化。借助这些工具,您可以构建适合您需求的强大调度程序应用程序。

我希望这篇文章能让您了解 cron 作业。感谢您阅读这篇文章。

以上是使用 React 和 Supabase 构建自定义调度程序的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
JavaScript在行动中:现实世界中的示例和项目JavaScript在行动中:现实世界中的示例和项目Apr 19, 2025 am 12:13 AM

JavaScript在现实世界中的应用包括前端和后端开发。1)通过构建TODO列表应用展示前端应用,涉及DOM操作和事件处理。2)通过Node.js和Express构建RESTfulAPI展示后端应用。

JavaScript和Web:核心功能和用例JavaScript和Web:核心功能和用例Apr 18, 2025 am 12:19 AM

JavaScript在Web开发中的主要用途包括客户端交互、表单验证和异步通信。1)通过DOM操作实现动态内容更新和用户交互;2)在用户提交数据前进行客户端验证,提高用户体验;3)通过AJAX技术实现与服务器的无刷新通信。

了解JavaScript引擎:实施详细信息了解JavaScript引擎:实施详细信息Apr 17, 2025 am 12:05 AM

理解JavaScript引擎内部工作原理对开发者重要,因为它能帮助编写更高效的代码并理解性能瓶颈和优化策略。1)引擎的工作流程包括解析、编译和执行三个阶段;2)执行过程中,引擎会进行动态优化,如内联缓存和隐藏类;3)最佳实践包括避免全局变量、优化循环、使用const和let,以及避免过度使用闭包。

Python vs. JavaScript:学习曲线和易用性Python vs. JavaScript:学习曲线和易用性Apr 16, 2025 am 12:12 AM

Python更适合初学者,学习曲线平缓,语法简洁;JavaScript适合前端开发,学习曲线较陡,语法灵活。1.Python语法直观,适用于数据科学和后端开发。2.JavaScript灵活,广泛用于前端和服务器端编程。

Python vs. JavaScript:社区,图书馆和资源Python vs. JavaScript:社区,图书馆和资源Apr 15, 2025 am 12:16 AM

Python和JavaScript在社区、库和资源方面的对比各有优劣。1)Python社区友好,适合初学者,但前端开发资源不如JavaScript丰富。2)Python在数据科学和机器学习库方面强大,JavaScript则在前端开发库和框架上更胜一筹。3)两者的学习资源都丰富,但Python适合从官方文档开始,JavaScript则以MDNWebDocs为佳。选择应基于项目需求和个人兴趣。

从C/C到JavaScript:所有工作方式从C/C到JavaScript:所有工作方式Apr 14, 2025 am 12:05 AM

从C/C 转向JavaScript需要适应动态类型、垃圾回收和异步编程等特点。1)C/C 是静态类型语言,需手动管理内存,而JavaScript是动态类型,垃圾回收自动处理。2)C/C 需编译成机器码,JavaScript则为解释型语言。3)JavaScript引入闭包、原型链和Promise等概念,增强了灵活性和异步编程能力。

JavaScript引擎:比较实施JavaScript引擎:比较实施Apr 13, 2025 am 12:05 AM

不同JavaScript引擎在解析和执行JavaScript代码时,效果会有所不同,因为每个引擎的实现原理和优化策略各有差异。1.词法分析:将源码转换为词法单元。2.语法分析:生成抽象语法树。3.优化和编译:通过JIT编译器生成机器码。4.执行:运行机器码。V8引擎通过即时编译和隐藏类优化,SpiderMonkey使用类型推断系统,导致在相同代码上的性能表现不同。

超越浏览器:现实世界中的JavaScript超越浏览器:现实世界中的JavaScriptApr 12, 2025 am 12:06 AM

JavaScript在现实世界中的应用包括服务器端编程、移动应用开发和物联网控制:1.通过Node.js实现服务器端编程,适用于高并发请求处理。2.通过ReactNative进行移动应用开发,支持跨平台部署。3.通过Johnny-Five库用于物联网设备控制,适用于硬件交互。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热工具

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

VSCode Windows 64位 下载

VSCode Windows 64位 下载

微软推出的免费、功能强大的一款IDE编辑器

EditPlus 中文破解版

EditPlus 中文破解版

体积小,语法高亮,不支持代码提示功能

螳螂BT

螳螂BT

Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用