Meteor:从客户端访问函数,在服务器上运行

Meteor:从客户端访问函数,在服务器上运行,meteor,methods,public,Meteor,Methods,Public,我正在尝试创建一个使用Steam API的程序。我希望能够调用该方法从客户机检索用户信息,同时对客户机保密该方法的实际代码,因为它包含一个API密钥。我尝试在服务器文件夹中将这些方法定义为全局方法,如下所示: key = 'xxxxxxxxxxxxxxxx'; Meteor.steamFunctions = { getName: function(user){ var userSteamId = user.profile.id; Meteor.http.

我正在尝试创建一个使用Steam API的程序。我希望能够调用该方法从客户机检索用户信息,同时对客户机保密该方法的实际代码,因为它包含一个API密钥。我尝试在服务器文件夹中将这些方法定义为全局方法,如下所示:

key = 'xxxxxxxxxxxxxxxx';

Meteor.steamFunctions = {
    getName: function(user){
        var userSteamId = user.profile.id;
        Meteor.http.get('http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key=' + key + '&steamids=' + userSteamId, function(error, resultJSON){
            if (error){
                return 'Error in Steam API';
            } else {
                var json = JSON.parse(resultJSON);
                return json.personaname;
            }
        })
    },

    getPic: function(user){
        var userSteamId = user.profile.id;
        Meteor.http.get('http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key=' + key + '&steamids=' + userSteamId, function(error, resultJSON){
            if (error){
                return 'Error in Steam API';
            } else {
                var json = JSON.parse(resultJSON);
                return json.avatarfull;
            }
        })
    }
}
然后,我尝试在客户端脚本中这样调用它:

if (Meteor.isClient){
    Template.profile.helpers({
        'getName': function(){
            return Meteor.steamFunctions.getName(Meteor.user());
        }
    });
}
然而,这会让人感到失望

Exception in template helper: TypeError: Cannot read property 'getName' of undefined
    at Object.Template.profile.helpers.getName

在仍然访问数据的情况下,如何对用户保密?

好吧,这并不像向Meteor全局添加属性那么简单。此外,执行此操作的远程方法/调用API将涉及异步代码

在服务器端,以仅在服务器上可见的代码(例如,
/server
子目录)使用机密API密钥对API进行调用。在服务器端定义可在客户端调用的

在服务器端Meteor方法中,您可以检查登录的用户或用户ID,并使用它来决定是进行调用还是忽略请求。如果请求不正确或出现错误,您可以从服务器端抛出一个新的Meteor.Error,但这需要资源进行通信

关于Meteor,需要了解的是,改变Javascript在浏览器或服务器上的行为并没有什么神奇之处。服务器最终运行的是nodejs。服务器上定义的对象不会神奇地迁移到客户端,反之亦然。如果一个对象是在这两者上定义的,那么它实际上是两段独立的代码

因此,在客户端代码中,
Meteor.call
从浏览器调用服务器端代码。。。实际上使用的是一个现有的websocket或ajax API,本质上是异步的。这意味着您需要构造客户端代码,以便在浏览器上提供回调函数,以处理查找
Name
Pic
的异步返回结果。直接返回和命令式编码样式是不可能的

通常,您需要根据查找返回的信息更新用户屏幕上的某些内容。通常的Meteor编码是使用
Session.set()
更新回调函数。模板可以引用这些会话变量,并通过隐式或显式Tracker.autorun()在API返回数据时更新屏幕。

您需要:

  • 将仅在服务器上定义的
    蒸汽函数
    移动到其中
  • 从客户端正确地调用这些方法
  • 下面是一些基于原始问题的示例代码。请注意,这尚未测试,可能需要一些调整

    server/methods.js

    const KEY='xxxxxxxxxxxxxx';
    常量URL=http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002';
    流星法({
    getName(){
    const userSteamId=Meteor.user().profile.id;
    常量参数={
    钥匙:钥匙,
    streamid:userstreamid,
    };
    试一试{
    var result=HTTP.get(URL,{params});
    //仔细检查这个-我不知道这个API返回了什么
    //您需要的数据可以嵌套在结果下,如result.data或其他内容。
    返回JSON.parse(result.PersonalName);
    }捕获(e){
    //发生了一些不好的事情-可能会抛出一个错误。
    返回false;
    }
    },
    });
    
    注意此方法是在服务器上定义的,因此我们不会将
    公开给客户端。还要注意,我们使用的是HTTP
    api的同步版本,因此可以将值返回给客户端

    client/lib/user.js

    Tracker.autorun(函数(){
    user=Meteor.user();
    if(user&&user.profile&&user.profile.id){
    Meteor.call('getName',(err,name)=>{
    Session.set('streamname',name);
    });
    }否则{
    Session.set('streamname','');
    }
    });
    
    更新用户日志时,获取steam名称并设置全局会话变量

    client/templates/profile.js

    Template.profile.helpers({
    getName:函数(){
    return Session.get('streamname');
    },
    });
    

    阅读模板中使用的
    steamName
    会话变量。

    感谢您的回复。。。我现在的问题是,该方法是在用户实际“登录”之前从客户端调用的,因此给了我一个“无法从未定义访问”错误。。我尝试在iron router文件中使用waitOn Meteor.user(),我还尝试安装fast render。。。两者似乎都不起作用。你知道一种更简单的方法来完成等待吗?不管怎样,谢谢你的回答,我真的很感激:)是的,这应该是一个简单的解决办法。在我添加它之前,您能告诉我steam名称何时更改以及概要文件模板何时呈现吗?例如,如果名称从未更改,并且配置文件被大量呈现,那么您将进行大量不必要的调用。在这种情况下,它应该是全局设置的。所以。。。我走了另一条路,我不确定这条路是否可行/正确。我在考虑创建一个集合,其中包含所有信息,信息被插入onCreateUser(),并在每次使用onLogin()登录时调用和更新信息。。。然后让他们通过收集访问数据。然而,我不确定这是否是完成任务的最佳方式。你对此有什么意见吗?对不起,我想带你去兜风。。。我只是不知道最好的方法:)有很多方法可以解决这个问题。您的建议听起来不错,但您可能希望直接写入用户的文档,而不是使用另一个集合-我想这取决于需要的数据量和内容。我用一个使用全局自动运行和会话变量的示例更新了答案。这是一个简单的解决方案,应该在适当的时候更新。唯一一次我不想