前端GraphQL客户端:优雅地获取数据

前端GraphQL客户端:优雅地获取数据

毒舌时刻

前端GraphQL?这不是后端的事吗?

"REST API就够了,为什么要用GraphQL"——结果前端需要多次请求,数据冗余,
"GraphQL太复杂了,我学不会"——结果错过了更灵活的数据获取方式,
"我直接用fetch请求GraphQL,多简单"——结果缺少缓存、错误处理等功能。

醒醒吧,GraphQL不是后端的专利,前端也需要专业的客户端工具!

为什么你需要这个?

  • 减少网络请求:一次请求获取所有需要的数据
  • 数据精确:只获取需要的数据,避免冗余
  • 类型安全:自动生成TypeScript类型
  • 缓存优化:智能缓存,减少重复请求
  • 开发效率:简化数据获取逻辑

反面教材

// 反面教材:直接使用fetch请求GraphQL async function fetchGraphQL(query, variables) { const response = await fetch('https://api.example.com/graphql', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ query, variables }), }); const data = await response.json(); if (data.errors) { console.error('GraphQL errors:', data.errors); throw new Error('GraphQL request failed'); } return data.data; } // 反面教材:重复请求相同数据 async function loadUserAndPosts() { // 第一次请求用户信息 const { user } = await fetchGraphQL(` query GetUser($id: ID!) { user(id: $id) { id name email } } `, { id: 1 }); // 第二次请求用户的帖子 const { user: userWithPosts } = await fetchGraphQL(` query GetUserWithPosts($id: ID!) { user(id: $id) { id posts { id title content } } } `, { id: 1 }); return { user, posts: userWithPosts.posts }; } 

正确的做法

// 正确的做法:使用Apollo Client import { ApolloClient, InMemoryCache, gql } from '@apollo/client'; // 创建Apollo Client实例 const client = new ApolloClient({ uri: 'https://api.example.com/graphql', cache: new InMemoryCache(), headers: { authorization: localStorage.getItem('token') || '' } }); // 定义查询 const GET_USER_WITH_POSTS = gql` query GetUserWithPosts($id: ID!) { user(id: $id) { id name email posts { id title content createdAt } } } `; // 定义变更 const CREATE_POST = gql` mutation CreatePost($input: PostInput!) { createPost(input: $input) { id title content createdAt } } `; // 在React组件中使用 import React from 'react'; import { useQuery, useMutation } from '@apollo/client'; function UserProfile({ userId }) { // 使用useQuery钩子获取数据 const { loading, error, data, refetch } = useQuery(GET_USER_WITH_POSTS, { variables: { id: userId }, // 缓存策略 fetchPolicy: 'cache-and-network' }); // 使用useMutation钩子执行变更 const [createPost, { loading: creating }] = useMutation(CREATE_POST, { // 变更后更新缓存 update(cache, { data: { createPost } }) { const { user } = cache.readQuery({ query: GET_USER_WITH_POSTS, variables: { id: userId } }); cache.writeQuery({ query: GET_USER_WITH_POSTS, variables: { id: userId }, data: { user: { ...user, posts: [...user.posts, createPost] } } }); } }); if (loading) return <div>加载中...</div>; if (error) return <div>错误:{error.message}</div>; const handleCreatePost = async (title, content) => { await createPost({ variables: { input: { title, content, userId } } }); }; return ( <div> <h2>{data.user.name}</h2> <p>{data.user.email}</p> <h3>帖子</h3> <ul> {data.user.posts.map(post => ( <li key={post.id}> <h4>{post.title}</h4> <p>{post.content}</p> <p>{post.createdAt}</p> </li> ))} </ul> <button onClick={() => refetch()}>刷新</button> <button onClick={() => handleCreatePost('新帖子', '帖子内容')} disabled={creating} > {creating ? '创建中...' : '创建帖子'} </button> </div> ); } // 正确的做法:使用URQL import { createClient, gql } from 'urql'; // 创建URQL客户端 const client = createClient({ url: 'https://api.example.com/graphql', fetchOptions: () => ({ headers: { authorization: localStorage.getItem('token') || '' } }) }); // 在React组件中使用 import React from 'react'; import { useQuery, useMutation } from 'urql'; function UserList() { const [result, reexecuteQuery] = useQuery({ query: gql` query GetUsers { users { id name email } } ` }); const { data, fetching, error } = result; if (fetching) return <div>加载中...</div>; if (error) return <div>错误:{error.message}</div>; return ( <div> <h2>用户列表</h2> <ul> {data.users.map(user => ( <li key={user.id}> {user.name} - {user.email} </li> ))} </ul> <button onClick={() => reexecuteQuery()}>刷新</button> </div> ); } // 正确的做法:使用Relay import { Environment, Network, RecordSource, Store, useLazyLoadQuery, graphql } from 'relay-runtime'; // 创建Relay环境 function fetchQuery(operation, variables) { return fetch('https://api.example.com/graphql', { method: 'POST', headers: { 'Content-Type': 'application/json', authorization: localStorage.getItem('token') || '' }, body: JSON.stringify({ query: operation.text, variables, }), }).then(response => { return response.json(); }); } const environment = new Environment({ network: Network.create(fetchQuery), store: new Store(new RecordSource()), }); // 定义查询 const UserQuery = graphql` query UserQuery($id: ID!) { user(id: $id) { id name email posts { edges { node { id title content } } } } } `; // 在React组件中使用 function UserDetail({ userId }) { const data = useLazyLoadQuery( UserQuery, { id: userId } ); return ( <div> <h2>{data.user.name}</h2> <p>{data.user.email}</p> <h3>帖子</h3> <ul> {data.user.posts.edges.map(edge => ( <li key={edge.node.id}> <h4>{edge.node.title}</h4> <p>{edge.node.content}</p> </li> ))} </ul> </div> ); } 

毒舌点评

看看,这才叫前端GraphQL客户端!不是简单地使用fetch请求,而是使用Apollo Client、URQL或Relay等专业的客户端工具。

记住,GraphQL客户端不仅仅是发送请求,还包括缓存管理、错误处理、类型生成等功能。这些工具可以大大简化你的前端代码,提高开发效率。

所以,别再觉得GraphQL复杂了,使用专业的客户端工具,让数据获取变得更加优雅!

总结

  • Apollo Client:功能强大,生态丰富,适合大型应用
  • URQL:轻量级,API简洁,适合中小型应用
  • Relay:Facebook开发,性能优异,适合大型应用
  • 缓存管理:智能缓存,减少重复请求
  • 类型安全:自动生成TypeScript类型
  • 错误处理:统一的错误处理机制
  • 变更管理:执行GraphQL变更并更新缓存
  • 开发工具:GraphQL Playground、Apollo DevTools等

前端GraphQL客户端,让数据获取变得更加优雅!

Read more

Aimmy未来路线图:即将推出的新功能与改进

Aimmy未来路线图:即将推出的新功能与改进 【免费下载链接】AimmyUniversal Second Eye for Gamers with Impairments (Universal AI Aim Aligner - YOLOv8) 项目地址: https://gitcode.com/gh_mirrors/ai/Aimmy Aimmy作为一款面向游戏玩家的通用AI瞄准辅助工具,正持续进化以提供更优质的游戏体验。本文将详细介绍Aimmy未来版本的开发计划,包括性能优化、功能增强和用户体验改进等关键方向。 Aimmy V2界面展示 - 紫色主题的现代化UI设计,集成多种瞄准辅助控制选项 一、核心性能优化:更快更精准的AI瞄准 1.1 目标检测算法升级 开发团队计划引入基于YOLOv9的新一代目标检测模型,相比当前使用的YOLOv8,预计可提升20%的检测速度和15%的准确率。新模型将特别优化远距离目标和快速移动目标的识别能力,代码实现将在AIManager.cs中进行核心更新。 1.2

LLaMA Factory全攻略:从环境搭建到模型部署的一站式解决方案

LLaMA Factory全攻略:从环境搭建到模型部署的一站式解决方案 作为一名IT运维工程师,当公司需要部署一个微调好的大模型时,面对复杂的AI技术栈和依赖环境,往往会感到无从下手。LLaMA Factory正是为解决这一痛点而生的开源工具,它提供了一套完整的低代码解决方案,让你无需深入AI技术细节也能快速完成大模型的微调与部署。本文将带你从零开始,逐步掌握LLaMA Factory的核心使用方法。 为什么选择LLaMA Factory? LLaMA Factory是一个开源的全栈大模型微调框架,它集成了业界广泛使用的微调技术,通过Web UI界面实现零代码操作。对于缺乏AI经验的运维人员来说,它具有以下优势: * 开箱即用:预置了多种流行大模型支持,包括LLaMA、Qwen、ChatGLM等 * 可视化操作:无需编写代码即可完成模型训练、微调和部署 * 资源友好:提供显存优化策略,降低硬件门槛 * 全流程覆盖:从数据准备到模型部署的一站式解决方案 这类任务通常需要GPU环境支持,目前ZEEKLOG算力平台提供了包含该镜像的预置环境,可快速部署验证。 环境准备

Qwen3-ASR-1.7B实战案例:新闻发布会实时语音转写+关键人物发言自动提取

Qwen3-ASR-1.7B实战案例:新闻发布会实时语音转写+关键人物发言自动提取 1. 项目背景与需求场景 新闻发布会是信息传播的重要场合,但传统的记录方式存在诸多痛点:人工记录容易遗漏关键信息,多人发言时难以准确区分说话人,后期整理需要耗费大量时间。特别是在大型发布会中,多位嘉宾轮流发言,快速准确地记录和提取每个人的讲话内容成为刚需。 Qwen3-ASR-1.7B语音识别系统正是为解决这些问题而生。相比之前的0.6B版本,这个1.7B参数的模型在识别准确率、上下文理解能力和多语言处理方面都有显著提升,特别适合处理新闻发布会这类复杂语音场景。 2. 系统核心能力解析 2.1 高精度语音识别引擎 Qwen3-ASR-1.7B采用深度神经网络架构,具备强大的语音特征提取能力。模型能够准确识别各种口音、语速和发音习惯,即使在有背景噪音的发布会现场也能保持较高的识别准确率。其1.7B的参数量确保了模型对上下文有更好的理解,能够根据语境自动修正识别错误。 2.2 智能说话人分离 系统内置先进的声纹识别技术,能够自动区分不同的说话人。通过分析每个人的声音特征,系统可以为每个发

AMD 显卡笔记本windows11满血玩转Stable Diffusion

AMD 显卡笔记本windows11满血玩转Stable Diffusion

电脑配置: AMD Ryzen R7 6800H,16G内存,核显Radeon 680M,共享内存8G。 测试了direct-ml版,还是zluda版本速度快,大概是direct-ml版本的5倍以上。以下正文。 一,安装 AMD HIP SDK HIP HIP(Heterogeneous-Compute Interface for Portability)是AMD开发的一种GPU编程模型,旨在实现GPU代码的可移植性。 AI应用里,N卡几乎可以说一统江湖,N卡的GPU是运行在CUDA平台上的。 HIP 可以说是 CUDA API 的”山寨克隆“版,几乎全盘拷贝 CUDA API,是 CUDA 的一个子集。 HIP可以运行在ROCm平台,也可以运行在CUDA平台(即可以运行在A卡,也可以运行在N卡上)。 ROCm介绍 ROCm是AMD的开源GPU计算软件堆栈,旨在提供一个可移植、高性能的GPU计算平台。