zl程序教程

您现在的位置是:首页 >  数据库

当前栏目

基于eos的Dapp开发--元素战争(四)

2023-03-15 22:08:24 时间

上节内容中我们讲了前端和智能合约之间通过一个service组件进行交互,并将前端的数据通过push action的方式存储到多索引表中。那么我们如何从智能合约的表中取数据出来并展示在前端界面呢,这便是我们今天要学习的内容。

对eos有一定了解的朋友们应该知道RPC接口的存在,我们可以通过cleos命令行的get table来获取表中的内容,也可以通过RPC接口中的get_table_rows来获取相关内容然后展示在前端页面上,其主要流程可以按照下图展示,我们接下来就来看这些操作是如何实现的:

在上一节内容中我们引入了ApiService的概念,接下来让我们在ApiService中添加一个获取当前用户信息的接口getUserByName(),username将是这个函数的唯一参数,当然通过上面的介绍我们很容易联想到RPC接口中的get_table_rows,我们具体来看代码:

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:

import { connect } from 'react-redux';
// Game subcomponents
import { PlayerProfile } from './components';

constructor在Game组件启动之前获取多索引表中的数据:

  constructor(props) {
    // 初始化构造函数
    super(props);
    // 绑定
    this.loadUser = this.loadUser.bind(this);
    this.loadUser();
  }

loaduser,通过ApiService里的getUserByName获取最新的玩家的数据:

  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中,从而实现自动登录的功能:

  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接口,最终实现表内容的查询以及展示,最后关于前端页面刷新的处理做了介绍。