当前位置: 首页 > Web前端 > HTML5

翻译-《JavaScript Everywhere》第六章CRUD操作(^_^)

时间:2023-04-05 16:29:36 HTML5

翻译|《JavaScript Everywhere》Chapter6CRUDOperation(^\_^)是顶级前端开发工程师写的。翻译一本英文技术书籍。为了提高大家的阅读体验,对句子的结构和内容进行了微调。如果大家发现本文有什么不妥之处,或者有什么意见和建议,可以在评论区留言,或者加我的微信:code\_maomao,欢迎交流,互相学习。(σ???)σ..:\*☆OuchnotbadChapter6CRUDOperations第一次听到“CRUDapplication”这个词,我误以为它指的是用来执行一些肮脏或Tricky应用程序的东西。不可否认,“CRUD”听起来像是从鞋底刮掉的东西。事实上,这个首字母缩略词在80年代早期被英国技术作家JamesMartin引用,用于创建、读取、更新和删除数据的应用程序。尽管该术语已经存在超过25年,但它仍然适用于当今开发的许多应用程序。想一想您每天与之交互的应用程序,例如待办事项列表、电子表格、内容管理系统、文本编辑器、社交媒体网站、应用程序和其他几个应用程序,其中很多可能都属于CRUD类别申请格式。用户可用于创建一些数据、访问或读取数据,并可用于更新或删除该数据。我们的Noted应用程序将遵循CRUD模式。用户将能够创建、阅读、更新和删除自己的笔记。在本章中,我们将通过连接解析器和数据库来实现API的基本CRUD功能。分离我们的GraphQL模式和解析器目前,我们的src/index.js文件是Express/Apollo服务器代码使用API的结构和解析器的地方。可以想象,随着我们代码库的增长,这可能会变得有点笨拙。在我们这样做之前,让我们花一些时间做一个小的重构来分离我们的结构、解析器和服务器代码。首先,我们将在src文件夹中创建一个名为src/schema.js的新文件,然后将在typeDefs变量中找到的模式内容移动到该文件中。为此,我们还需要导入apollo-server-express包附带的gql模式语言,并使用Node将我们的模式导出为module.exports方式。首先,让我们将GraphQL模式移动到它自己的文件中。在此过程中,我们还可以使用删除hello查询,在最终应用程序中将不再需要它:const{gql}=require('apollo-server-express');module.exports=gql`typeNote{id:ID!内容:字符串!作者:字符串!}typeQuery{注意:[注意!]!注意(id:ID!):注意!}typeMutation{newNote(content:String!):注意!}`;我们现在可以通过导入这个外部结构文件来更新src/index.js文件,并从apolloserverexpress中删除导入的gql,如下所示:const{ApolloServer}=require('apollo-server-express');consttypeDefs=require('./schema');现在我们已经将GraphQL模块隔离到它自己的文件中,让我们对GraphQL解析器代码做一些类似的事情。我们的解析器代码将包含绝大多数API逻辑,因此首先我们将创建一个文件夹来存储此代码,称为解析器。在src/resolvers目录中,我们将从三个文件开始:src/resolvers/index.js、src/resolvers/query.js和src/resolvers/mutation.js。与我们在数据库模块中遵循的模式类似,src/resolvers/index.js文件将用于将解析器代码导入单个导出模块。继续按如下方式设置文件:constQuery=require('./query');constMutation=require('./mutation');module.exports={查询,变异};现在你可以使用查询代码设置src/resolvers/query.js:module.exports={notes:async()=>{returnawaitmodels.Note.find()},note:async(parent,args)=>{返回等待模型。注意.findById(args.id);}}然后将修改代码移动到src/resolvers/mutation.js文件中::'亚当斯科特'});接下来,服务器通过将以下行添加到src/index.js文件来导入解析器代码:constresolvers=require('./resolvers');重构解析器的最后一步是将它们连接到我们的数据库模块。您可能已经注意到我们的解析器模块引用了这些模块,但无法访问它们。为了解决这个问题,我们将在ApolloServer中使用一个称为上下文的概念,它允许我们根据每个请求将特定信息从服务器代码传递到单个解析器。目前这可能有点矫枉过正,但它对于将用户身份验证合并到我们的应用程序中很有用。为此,我们将更新位于str/index.js中的ApolloServer启动代码,以传递返回数据库模块的上下文函数。//ApolloServersetupconstserver=newApolloServer({typeDefs,resolvers,context:()=>{//添加数据库模型到上下文return{models};}});现在,我们通过添加{modules}作为每个函数的第三个参数来做到这一点,然后更新每个解析器以利用这个上下文函数。在src/resolvers/query.js中执行如下操作:module.exports={notes:async(parent,args,{models})=>{returnawaitmodels.Note.find()},note:async(parent,args,{models})=>{returnawaitmodels.Note.findById(args.id);}}将修改代码移动到src/resolvers/mutation.js文件中:内容,作者:'AdamScott'});我们的src/index.js文件现在将简化如下:constexpress=require('express');const{ApolloServer}=require('apollo-server-express');require('dotenv').config();//本地模块导入constdb=require('./db');constmodels=require('./models');consttypeDefs=require('./schema');constresolvers=require('./resolvers');//在我们的.env文件中指定的端口或端口4000constport=process.env.PORT||上运行我们的服务器4000;constDB_HOST=process.env.DB_HOST;constapp=express();db.connect(DB_HOST);//Apollo服务器设置constserver=newApolloServer({typeDefs,resolvers,context:()=>{//将数据库模型添加到上下文return{models};}});//应用ApolloGraphQL中间件并将路径设置为/apiserver.applyMiddleware({app,path:'/api'});app.listen({port},()=>console.log(`GraphQL服务器运行在http://localhost:${port}${server.graphqlPath}`));编写我们的GraphQLCRUD模式现在我们已经重构了我们的代码以更加灵活,让我们开始实现CRUD操作。我们已经能够创建和阅读笔记,这使我们能够实现更新和删除功能。首先,我们要更新结构。由于更新和删除操作会更改我们的数据,因此它们将被修改。我们的更新笔记将需要一个ID参数来定位新笔记的笔记和内容。然后更新查询将返回新更新的注释。对于我们的删除操作,我们的API将返回一个布尔值true让我们知道笔记已成功删除。更新src/schema.js中的修改结构如下:typeMutation{newNote(content:String!):注意!updateNote(id:ID!,content:String!):注意!deleteNote(id:ID!):布尔值!有了这些添加,我们的结构现在就可以执行CRUD操作了。CRUD解析器现在我们有了我们的结构,可以更新解析器以删除或更新注释。让我们修改我们的deleteNote。要删除注释,我们将使用Mongoose的findOneAndRemove方法,将要删除的项目的ID传递给它。如果找到并删除了我们的项目,我们将向客户返回true,但如果我们无法删除该项目,则返回false。在src/resolvers/mutation.js中,在模块中添加module.exports对象:deleteNote:async(parent,{id},{models})=>{try{awaitmodels.Note.findOneAndRemove({_id:id});返回真;}catch(err){返回错误;}},现在我们可以在GraphQLPlayground中运行我们的修改。在Playground的新选项卡中,输入以下修改,确保使用数据库中其中一个笔记的ID:mutation{deleteNote(id:"5c7d1aacd960e03928804308")}如果笔记被成功删除,您应该收到一个trueresponse:{"data":{"deleteNote":true}}如果你传递一个不存在的ID,你会得到一个"deleteNote"response:false。使用我们的删除功能,让我们编写我们的updateNote修改。为此,我们将使用Mongoose的findOneAndUpdate方法。该方法将使用查询的初始参数在数据库中找到正确的注释,然后是第二个参数,我们将在其中设置新注释的内容。最后,我们将传递第三个参数new:true,它指示数据库向我们返回更新后的笔记内容。在src/resolvers/mutation.js中,添加module.exportsupdateNote:async(parent,{content,id},{models})=>{returnawaitmodels.Note.findOneAndUpdate({_id:id,},{$set:{content}},{new:true});},我们现在可以通过在浏览器中访问GraphQLPlayground来尝试我们的updateNote修改。在Playground的新选项卡中,使用id和content参数编写修改:mutation{updateNote(id:"5c7d1f0a31191c4413edba9d",content:"Thisisanupdatednote!"){idcontent}}如果我们的修改按预期工作有效,GraphQL响应应如下所示:如果我们传递了错误的ID,响应将失败,我们将收到一个内部服务器错误消息,并用错误更新注释。现在,我们可以使用它来创建、阅读、更新和删除笔记。这样我们的API就有了完整的CRUD功能。在创建数据库结构时,我们要求Mongoose在数据库中创建和更新条目时自动存储时间戳。此信息将在我们的应用程序中很有用,因为它允许我们在创建笔记或上次编辑笔记时在用户界面中向用户显示。让我们添加createdAt和updatedAt字段来保存这些值。您可能还记得GraphQL允许默认类型String、Boolean、Int、Float和ID。不幸的是,GraphQL没有内置的日期变量类型。我们可以使用String类型,但这意味着我们将无法利用GraphQL提供的类型验证来确保我们输入的日期时间内容必须是日期时间。相反,我们可以创建自定义变量类型。自定义类型允许我们定义一个新类型,并针对请求该类型数据的每个查询和修改对其进行验证。让我们通过在GQL字符串文字的顶部添加自定义变量来更新src/schema.js中的GraphQL模式:module.exports=gql`scalarDateTime...`;现在,添加createdAt和updatedAt字段:typeNote{id:ID!内容:字符串!作者:字符串!创建于:日期时间!updatedAt:DateTime!}最后一步是验证这个新类型。虽然我们可以编写自己的验证,但目前对于我们的用例,我们将使用graphql-iso-date包。现在,我们将向任何请求DateTime类型值的解析器函数添加验证。在src/resolvers/index.js文件中,导入包,然后像这样将DateTime值添加到导出的解析器中:constQuery=require('./query');constMutation=require('./mutation');const{GraphQLDateTime}=require('graphql-iso-date');module.exports={查询,变异,日期时间:GraphQLDateTime};现在,如果我们在浏览器中访问GraphQLPlayground并刷新页面,我们可以验证我们的自定义类型是否按预期工作。如果我们请求我们的字段,我们可以看到createdAt和updatedAt字段是格式化的日期时间。如图6-1所示,此类型的文档指出它是“UTC中的日期时间字符串”。图6-1。我们的结构现在有一个DateTime类型为了测试这一点,让我们在GraphQLPlayground中编写一个newNote突变,其中包括我们的日期字段:突变{newNote(内容:“这是一个自定义类型的笔记!”){内容作者IDcreatedAtupdatedAt}}这将返回createdAt和updatedAt值作为ISO格式的日期。如果我们对相同的字符修改再次运行updateNote,我们将看到一个与createdAt日期不同的updatedAt值。有关定义和验证自定义变量类型的更多信息,我建议阅读ApolloServer的“自定义变量和枚举”文档。结论在本章中,我们向API添加了创建、读取、更新和删除(CRUD)功能。CRUD是许多应用程序使用的一种非常常见的模式。我希望你看看你每天使用的应用程序,并考虑它们的数据如何使用这种模式。在下一章中,我们将向API添加用于创建和验证用户帐户的功能。如果有什么不明白的地方,请指正。如果觉得还可以,请点赞、收藏或分享,希望能帮助到更多的人。

猜你喜欢