【问题标题】:Meteor helpers run multiple times流星助手运行多次
【发布时间】:2015-09-15 09:58:07
【问题描述】:

助手在会话更改时(在同一页面上)运行多次(它们取决于会话,因为这是我选择加载哪些数据的方式)

  1. 我从 JSON (Meteor.http.get...) 获取数据 **检查服务器方法*

  2. API 密钥存储在用户(useraccounts 包,当前按预期工作)


API 密钥端点(如果需要):https://keeky.github.io/Guild-Wars-2-API-Explorer/#v2/account Meteorpad : 6mY7c6yf8pAjACyZe/Leaderboard (还没有检查它是否在那里工作)

视频(问题):http://webm.host/b8c71/vid.webm

客户端

myprofile.html

<template name="myprofile">
      <ul class="nav nav-tabs nav-justified" style="margin-bottom: 15px;">
          {{#each characterlist}}
        <li><a name="{{this}}" class="charactername" href="#">{{this}}</a></li>
          {{/each}}
    </ul>
    <div class="container">
    <div class="well">
      <h1 class="text-center">{{character_selected_name}}</h1>
      <h6 class="text-center">Level {{character_selected_data.level}} {{character_selected_data.profession}}</h6>
      <hr>
    </div>
    <div class="well">
      <h2 class="text-center">Bags</h2>
      <h5 class="text-center">
        {{#each character_selected_data.bags}}
        {{id}}
        {{/each}}
      </h5>
      <hr>
    </div>
    </div>
    <div class="footer-myprofile">
      <div class="row whitetext text-center boldtext">
        <div class="col-md-4">
          {{basicinfo.name}}
        </div>
        <div class="col-md-4">
          {{basicinfo.world}}
        </div>
        <div class="col-md-4">
          {{#each basicinfo.guilds }}
           {{this}}
          {{/each}}
        </div>
      </div>
    </div>
    </template>

myprofile_helpers.js

Template.myprofile.helpers({
  "basicinfo" : function(){
    Meteor.call("getmyprofilebasic", function(error,result){
      result.world = worlddata.findOne({"worldid":result.world}).name;
      Session.set("basicinfo",result);
    });
    return Session.get("basicinfo")
  },
  "characterlist" : function(){
    Meteor.call("getmyprofilecharacters", function(error,result){
      result = result.sort();
      Session.set("characterlist",result);
      Session.set("character_selected",result[0])
      console.log(result);
    });
    return Session.get("characterlist")
  },
  "character_selected_name": function(){
    return Session.get("character_selected")
  },
  "character_selected_data": function(){
    Meteor.call("getmyprofilecharacterdata",Session.get("character_selected"), function(error,result){
        console.log(result);
      Session.set("character_selected_data",result);
    });
      return Session.get("character_selected_data")
  }
});

myprofile_events.js

Template.myprofile.events({
  "click .charactername" : function(event,template){
    Session.set("character_selected",this.toString())
    event.preventDefault();
    return false
  }
});

服务器端

服务器方法(myprofile)

Meteor.users.deny({
  update: function() {
    return true;
  }
});

if (Meteor.isServer){
  Meteor.methods({
    "getmyprofilebasic" : function(){
      this.unblock();
      var userid = this.userId;
      console.log(userid);
      var apikey = Meteor.users.findOne({_id:userid}).profile.apikey;
      var url="https://api.guildwars2.com/v2/account?access_token=" + apikey;
            var result = Meteor.http.get(url, {timeout:30000});
            if(result.statusCode==200) {
                var respJson = JSON.parse(result.content);
                return respJson;
            } else {
                console.log("Response issue: ", result.statusCode);
                var errorJson = JSON.parse(result.content);
                throw new Meteor.Error(result.statusCode, errorJson.error);
            }
    },
    "getmyprofilecharacters" : function(){
      this.unblock();
     var userid = this.userId;
     var apikey = Meteor.users.findOne({_id:userid}).profile.apikey;
     var url="https://api.guildwars2.com/v2/characters?access_token=" + apikey;
     var result = Meteor.http.get(url, {timeout:30000});
     if(result.statusCode==200) {
       var respJson = JSON.parse(result.content);
       return respJson;
     } else {
       console.log("Response issue: ", result.statusCode);
       var errorJson = JSON.parse(result.content);
       throw new Meteor.Error(result.statusCode, errorJson.error);
     }
   },
   "getmyprofilecharacterdata" : function(name){
     this.unblock();
    var userid = this.userId;
    var apikey = Meteor.users.findOne({_id:userid}).profile.apikey;
    var url="https://api.guildwars2.com/v2/characters?access_token=" + apikey +"&ids=" +name;
    var result = Meteor.http.get(url, {timeout:30000});
    if(result.statusCode==200) {
      var respJson = JSON.parse(result.content);
      return respJson[0];
    } else {
      console.log("Response issue: ", result.statusCode);
      var errorJson = JSON.parse(result.content);
      throw new Meteor.Error(result.statusCode, errorJson.error);
    }
   }
  });
}

流星方法(getitemicon)

Meteor.methods({
  "getitemicon" : function(id){
    this.unblock();
    var url="https://api.guildwars2.com/v2/items?ids=" + id;
    var result = Meteor.http.get(url, {timeout:30000});
    if(result.statusCode==200) {
      var respJson = JSON.parse(result.content);
      return respJson[0].icon;
    } else {
      console.log("Response issue: ", result.statusCode);
      var errorJson = JSON.parse(result.content);
      throw new Meteor.Error(result.statusCode, errorJson.error);
  }
  }
});
Meteor.call("getitemicon",8932);

【问题讨论】:

  • 不是很明显,但那是很多代码。
  • 是的...将其减小到“可读”大小,因为我基本上添加了流星文件夹中的所有内容
  • 我没有通读您的所有代码,但您通常不应该从数据助手调用方法,而是从事件处理程序或跟踪器回调中调用方法。当你在一个 helper 中做这件事时,尤其是一个根据这个调用的副作用计算出来的 helper,这个 helper 会被运行多次,进行更多的调用,所以在最坏的情况下,它会被无限期地调用。跨度>

标签: meteor meteor-blaze


【解决方案1】:

这确实是很多代码,但模式最终会显露出来:您的 profile 页面需要需要对 guildwars2 api 进行多次 API 调用的信息。每个页面元素都使用一个帮助器一个会话变量来定义,每个元素都需要对服务器进行异步调用,服务器反过来对guildwars2进行API调用。呃。这不会一帆风顺。

这是一种替代方法,它也可以让您获得更好的性能和可读性。

  1. Template.myprofile.onCreated() 中创建一个Meteor.call
  2. 在该服务器调用 upsert 中,您需要从 guildwars2collection 的所有数据片段,例如:GuildWars2Data 组织该数据在你的 UI 中工作的结构。由于我怀疑您的 GuildWars2 数据与 Meteor 用户的比例为 1:1,因此该集合也应向用户键入。这个集合基本上是一个缓存。
  3. 确保您的客户端订阅了GuildWars2Data,并且服务器正在发布与登录用户相关的文档
  4. 确保在您的客户端代码中将数据上下文设置为当前用户的 GuildWards2Data 文档
  5. 然后在布局中正常使用文档中的元素,例如{{characterName}}。如果第 2 步做得好,除了设置数据上下文的帮助之外,您甚至可能不需要任何帮助。

此外,现在您应该能够放弃所有这些会话变量,因为您将有一个可供参考的集合。

现在我想知道为什么您首先要通过您的服务器来调解所有这些调用。如果每个用户都有自己的 GuildWars2 api 密钥,那么获取自己数据的代码可以简单地在客户端上运行。这将节省您在服务器上的负载,并为您的用户提供更快的速度。您需要小心地将用户的 API 密钥仅发布给拥有它们的用户。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-16
    • 1970-01-01
    • 2015-04-15
    相关资源
    最近更新 更多