上节内容中我们讲了前端和智能合约之间通过一个service组件进行交互,并将前端的数据通过push action的方式存储到多索引表中。那么我们如何从智能合约的表中取数据出来并展示在前端界面呢,这便是我们今天要学习的内容。
对eos有一定了解的朋友们应该知道RPC接口的存在,我们可以通过cleos命令行的get table来获取表中的内容,也可以通过RPC接口中的get_table_rows来获取相关内容然后展示在前端页面上,其主要流程可以按照下图展示,我们接下来就来看这些操作是如何实现的:
在上一节内容中我们引入了ApiService的概念,接下来让我们在ApiService中添加一个获取当前用户信息的接口getUserByName(),username将是这个函数的唯一参数,当然通过上面的介绍我们很容易联想到RPC接口中的get_table_rows,我们具体来看代码:
代码语言:javascript复制static async getUserByName(username) {
try {
//新建一个RPC对象
const rpc = new Rpc.JsonRpc(process.env.REACT_APP_EOS_HTTP_ENDPOINT);
const result = await rpc.get_table_rows({
//传参格式为JSON
"json": true,
"code": prodcess.env.REACT_APP_EOS_CONTRACT_NAME,
//code为合约账户名
"scope": process.env.REACT_APP_EOS_CONTRACT_NAME,
// 合约的scope
"table": "users",
// 要查询的表明
"limit": 1,
// 只查一个
"lower_bound": username,
//这个lower_bound和upper_bound建议参考以下multi-index.hpp学习哦
});
return result.rows[0];
} catch (err) {
console.error(err);
}
}
在上面的例子中我们使用了limit,lower_bound等限制,关于multi-index的内容,还是建议各位读者稍微阅读下源码,即multi-index.hpp中的一些内容,这样能更方便的理解多索引表,当然我以前的文章中也多次提及过:
eos源码赏析(十三):EOS智能合约数据持久化存储(上)
eos源码赏析(十四):EOS智能合约数据持久化存储(下)
eos源码赏析(十六):EOS智能合约数据表查询
getUserByName的返回结果将是一个JSON格式的字符串,包含了玩家的信息以及游戏的相关信息。
然后我们来创建一个PlayerProfile组件来展示上面接口返回的内容,PlayerProfile是React中一个用于展示内容的组件,在这里我们需要把他包含到Game组件内,做完以上内容我们可以发现:
mapStateToProps 和mapDispatchToProps已经被添加,用来链接组件和Redux store:
代码语言:javascript复制import { connect } from 'react-redux';
// Game subcomponents
import { PlayerProfile } from './components';
constructor在Game组件启动之前获取多索引表中的数据:
代码语言:javascript复制 constructor(props) {
// 初始化构造函数
super(props);
// 绑定
this.loadUser = this.loadUser.bind(this);
this.loadUser();
}
loaduser,通过ApiService里的getUserByName获取最新的玩家的数据:
代码语言:javascript复制 loadUser() {
const { setUser, user: { name } } = this.props;
// 通过ApiService发送请求,调用getUserByName然后在通过RPC接口中的get_table_rows来查询表中的数据,并解析展示出来
return ApiService.getUserByName(name).then(user => {
setUser({
win_count: user.win_count,
lost_count: user.lost_count,
game: user.game_data,
});
});
}
当PlayerProfile创建完成之后,我们在登录之后会看到已登录用户的信息,比如玩家名,赢的次数,输的次数等。但是有个问题需要注意,用户数据存储在了Redux store中,但是Redux store会在每次浏览器页面刷新之后进行重构,数据就会被清空,我们怎么来解决呢?
我们可以在ApiService中添加一个getCurrentUser函数从本地存储中来获取当前用户的信息,获取到之后可以调用智能合约的login action,如果登录成功了,我们就再次把用户数据存储到redux store中,从而实现自动登录的功能:
代码语言:javascript复制 static getCurrentUser() {
return new Promise((resolve, reject) => {
if (!localStorage.getItem("cardgame_account")) {
return reject();
}
takeAction("login", { username: localStorage.getItem("cardgame_account") })
.then(() => {
resolve(localStorage.getItem("cardgame_account"));
})
.catch(err => {
localStorage.removeItem("cardgame_account");
localStorage.removeItem("cardgame_key");
reject(err);
});
});
}
登录成功的页面如下所示:
本文承接上文,介绍如何从智能合约表中查询数据,从前端开始,调用ApiService然后在调用RPC接口,最终实现表内容的查询以及展示,最后关于前端页面刷新的处理做了介绍。