GraphQL实战比特币实时行情【NodeJS】

在这篇文章中,我们将学习如何使用Node.js开发一个比特币实时价格行情的GraphQL API。

比特币开发相关链接:

1、创建项目目录

在终端中执行如下命令创建一个新目录并进入该目录:

mkdir btc-gql-api && cd btc-gql-api

2、初始化项目

在终端中执行yarn init初始化项目目录,得到的package.json类似以下内容:

1{ 2 "name": "my-new-project", 3 "version": "1.0.0", 4 "description": "My New Project description.", 5 "main": "index.js", 6 "repository": { 7 "url": "https://example.com/your-username/my-new-project", 8 "type": "git" 9 }, 10 "author": "Your Name <you@example.com>", 11 "license": "MIT" 12}

在终端执行touch index.js创建一个空的js文件,然后在package.json中添加如下内容:

1... 2"scripts": { 3 "start": "node index.js" 4}, 5...

最终的package.json文件看起来类似如下内容:

1{ 2 "name": "my-new-project", 3 "version": "1.0.0", 4 "description": "My New Project description.", 5 "main": "index.js","scripts": { 6 "start": "node index.js" 7 }, 8 "repository": { 9 "url": "https://example.com/your-username/my-new-project", 10 "type": "git" 11 }, 12 "author": "Your Name <you@example.com>", 13 "license": "MIT" 14}

在项目目录中创建一个graph目录,得到如下的目录结构:

1+ btc-gql-api 2|__ graphql 3|__ package.json 4|__ index.json

在graph目录中创建3个js文件:types.js、resolver.js和request.js,最终得到如下的目录结构:

1+ btc-gql-api 2|__+graphql 3|____request.js 4|____resolvers.js 5|____types.js 6|__ package.json 7|__ index.json

3、安装依赖包

在这个项目中,我们将需要axios和graphql-yoga,因此在项目根目录 执行如下命令:

yarn add axios graphql-yoga

好了,可以开始写代码了。

4、类型定义

在GraphQL Schema中最基础的组件就是对象类型,它标识你可以从服务中提取的对象类型,以及其中包含哪些字段。例如:

1type User { 2 name: String! 3 email: String! 4}

GraphQL有一些内置的基础类型:

  • Int:32位有符号整数
  • Float:双精度有符号浮点数
  • String:UTF-8字符序列
  • Boolean:布尔型,true或false
  • ID:唯一标识符,通常用于作为对象的键

更详细的文档可以参考graphql schema

现在让我们定义类型。打开./graphql/types.js文件,输入如下内容:

1const typeDefs = ` 2scalar JSON 3 4type Price { 5 price:JSON! 6}`; 7 8module.exports = typeDefs;

在上面的代码中,我们定义了一个类型Price,它只有一个非空字段price,字段类型为JSON:

1type Price { 2 price:JSON! 3}

JSON并不是graphql的内置类型,是我们自定义的:

scalar JSON

5、查询

GraphQL是关于数据管理的,查询基本上就是请求对象的指定字段。 例如:

1query { 2 getPrices { 3 price 4 } 5}

得到如下结果:

1{ 2 "data": { 3 "getPrices": { 4 "price": { 5 "USD": { 6 "15m": 10436.54, 7 "last": 10436.54, 8 "buy": 10436.54, 9 "sell": 10436.54, 10 "symbol": "$" 11 } 12 ... 13 } 14 } 15 } 16}

可以看到,查询结果和请求有相同的结构。

6、查询与修改

在一个schema内有两种类型:查询(query)与修改(mutation)。

每个GraphQL服务至少有一个查询类型,可能有一个修改类型。这些类型和常规的对象类型一样,但是它们定义了每个GraphQL查询的入口点。看起来像这样:

1scalar JSON 2 3type Price { 4 price:JSON! 5} 6 7type Query { 8 getPrices: Price! 9 getPrice(currency:String!): Price! 10}

上面代码的意思是,我们的GraphQL服务有一个Query类型,其中包含 getPrices和getPrice字段,其类型都是Price。我们也可以看到字段 getPrice有参数(currency:String!)。在GraphQL对象类型中的每个 字段都可以有0或多个参数。

参数可以是必需的或可选的,在上面的例子中,我们要求一个必需的 参数currency用来选择要查询的币种。

7、请求辅助工具

在我们继续GraphQL之前,我们需要一个辅助工具来获取比特币实时价格。为此我们将使用blockchain.com的API,但是你可以换成任何你喜欢的服务。

打开./graphql/request.js文件,输入以下内容:

1const axios = require("axios");module.exports = { 2 getPrices: async () => { 3 const url = "https://blockchain.info/ticker"; 4 try { 5 return await axios.get(url); 6 } catch (error) { 7 console.error(error); 8 } 9 } 10};

上面的代码使用axios来构造GET请求,当然你也可以换成其他你熟悉的工具。

8、解析器

每个类型的每个字段背后都对应一个解析器函数,该函数应当由GraphQL服务端开发者提供。当一个字段执行时,对应的解析器就被调用并生成结果。

如果一个字段生成一个标量值例如字符串或数字,那么执行就结束了。然而,如果一个字段生成一个对象值,那么查询将包含另外的字段,这将继续解析直到最终得到的字段都是标量值。

每个GraphQL服务的顶层是所有可能的入口类型,通常被称为根(Root)类型或查询(Query)类型。

打开文件./graphql/resolvers.js,输入以下内容:

1const requests = require("./requests"); 2const resolvers = { 3 Query: { 4 // Get all available prices 5 async getPrices(parent, args, ctx, info) { 6 const prices = await requests.getPrices(); 7 return { price: prices.data }; 8 }, 9 // Get the price of a given currency symbol 10 async getPrice(parent, args, ctx, info) { 11 const prices = await requests.getPrices(); 12 return { price: { [args["currency"]]: prices.data[args["currency"]] } }; 13 } 14 } 15}; 16module.exports = resolvers;

让我们分解说明下以上代码。

首先引入我们查询比特币实时行情的辅助工具:

const request = require("./request");

然后定义解析器:

1const resolvers = { 2 Query: { 3 // Get all available prices 4 async getPrices(parent, args, ctx, info) { 5 const prices = await requests.getPrices(); 6 return { price: prices.data }; 7 }, 8 // Get the price of a given currency symbol 9 async getPrice(parent, args, ctx, info) { 10 const prices = await requests.getPrices(); 11 return { price: { [args["currency"]]: prices.data[args["currency"]] } }; 12 } 13 } 14};

我们的解析器有一个根字段Query,在该对象内我们将定义GraphQL Schema中的所有解析器。注意这些解析器的命名与types.js中一致。

每个解析器都是一个函数,有4个参数:

  • parent:父对象
  • args:参数
  • ctx:上下文
  • info:字段特定信息

9、服务器

现在我们已经有了类型、解析器和辅助工具,要做的就是整合起来。

打开index.js文件,输入以下内容:

1const { GraphQLServer } = require("graphql-yoga"); 2const typeDefs = require("./graphql/types.js"); 3const resolvers = require("./graphql/resolvers.js"); 4const server = new GraphQLServer({ 5 typeDefs, 6 resolvers, 7 context: { 8 //if we pass anything here can be available in all resolvers 9 } 10}); 11server.start(() => console.log("Server is running on localhost:4000☄"));

首先我们创建GraphQLServer实例:

1... 2const server = new GraphQLServer({ 3 typeDefs, 4 resolvers, 5 context: { 6 //if we pass anything here can be available in all resolvers 7 } 8}); 9...

然后运行该实例:

server.start(() => console.log("Server is running on localhost:4000☄"));

运行后可以看到如下输出:

Server is running on localhost:4000☄

现在打开浏览器访问http://localhost:4000,测试如下查询:

1query($currency:String!){ 2 getPrice(currency:$currency){ 3 price 4 } 5} 6# Variables: 7{ 8 "currency": "USD" 9}

得到如下结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FUdB6giq-1582590529946)(bitcoin-graphql-api/query-result.png)]

非常好!


原文链接:用Node.jS开发比特币行情GraphQL API — 汇智网

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )