与 Durandal 合作的第一个 javascript 项目。尝试从第 3 方获取数据 API

First javascript project with Durandal. Trying to get data from 3rd party API

所以我正在做一个项目,在这个项目中,游戏玩家将能够将他们的表现与处于相同技能水平的同龄人进行比较。我可以获得在 durandal 结构之外工作的代码原型,但是当我在提供自己的数据源的同时尝试遵循其他示例时,我就是无法将它们全部整合在一起。

这是我的代码:

define(function (require) {
var http = require('plugins/http'),
    ko = require('knockout');
var url = 'https://na.api.pvp.net/api/lol/na/v1.4/summoner/by-name/',
    key = '?api_key=#################################';

return {
    name: ko.observable,
    getSummoner: function() {
        var that = this;
        if (this.name.length > 0) {
            return;
        }
        return http.jsonp(url + name + key, 'jsoncallback').then(function(response){
            that.name(response.items);
        });
    }
};
}); 

将 # 替换为我个人的 API 密钥,主持人建议我不要共享。如有必要,我会提供一个,稍后再更改。

我这里有 2 个具体问题:

  1. 我从教程中得到了函数结构。我不知道为什么我需要用 IF 语句检查长度。返回的到底是什么?

  2. 这个 api 调用 returns 一个 JSON 对象,里面有一个嵌套对象。我想要的是将嵌套对象中的键和值显示为视图中的 li。现在我什至无法让它告诉我它是否真的抓住了物体。

这是我的HTML:

<section>
  <h2>Hello! What user would you like to investigate?</h2>
  <form class="form-inline">
    <fieldset>
       <label>Name</label>
       <input type="text" data-bind="value: name, valueUpdate: 'afterkeydown'"/> <!--Text input box-->
       <button type="submit" class="btn" data-bind="click: getSummoner, enable: name">Click Me</button><!--This button has both a class and an ID, 
       Css is linked from index.html-->
       <ul data-bind="foreach: name">
            <li data-bind="text:$data"></li>
        </ul>
    </fieldset>
  </form>
</section>

我希望看到的只是 1 个项目符号项,它表示对象或输入框中输入的任何名称。我得到的是什么。

返回的对象(附有我的用户名)如下所示:

{"ryebrush":{"id":25500750,"name":"RyeBrush","profileIconId":551,"summonerLevel":30,"revisionDate":1426533699000}}

我希望能够访问 ryebrush.id、ryebrush.profileIconId 等等。有帮助吗?

编辑:此外,它已预加载到输入框中:

function (b){function c(){if(0<arguments.length)return c.Ka(d,arguments[0])&&(c.P(),d=arguments[0],c.O()),this;a.k.zb(c);return d}var d=b;a.N.call(c);a.a.sa(c,a.m.fn);c.o=function(){return d};c.O=function(){c.notifySubscribers(d)};c.P=function(){c.notifySubscribers(d,"beforeChange")};a.s(c,"peek",c.o);a.s(c,"valueHasMutated",c.O);a.s(c,"valueWillMutate",c.P);return c}

啊啊啊啊……什么?

你问了两个问题,所以我会给你两个半的答案。

在我们解决您的第一个问题之前,您错误地使用了 knockout observable 函数,这会让您很头疼。让我们解决这个问题。以下两行代码的工作方式类似。当您调用 observable 函数时,您创建了一个新的 observable 实例。如果不带参数调用它,则可观察值的值为 undefined。由于我们知道您需要一个字符串,因此最好将其初始化为空字符串,如第二个示例所示。

name: ko.observable(),

name: ko.observable(''),

然后,我们可以通过将其作为函数调用来设置或检索可观察对象的值:

that.name('value');

that.name() == 'value';

I got the function structure from a tutorial. I don't know why I need to check for length with the IF statement. What is that returning exactly?

在 if 语句之后,您有以下代码行:

http.jsonp(url + name + key, 'jsoncallback')

如果名称未定义或为空,您将尝试分别对两个网址之一进行此调用:

https://na.api.pvp.net/api/lol/na/v1.4/summoner/by-name/undefined/?api_key=#

https://na.api.pvp.net/api/lol/na/v1.4/summoner/by-name//?api_key=#

我们知道两者都应该 return 一个错误(可能是 400),所以进行这些调用没有意义。当应用于字符串时,if 语句在字符串已初始化且为空时为真。请注意,如果字符串是 undefined,这将引发错误,这并不好。

但是,语法也是错误的。从技术上讲,that.name 的值是一个函数,当被视为字符串时,将计算为

function (b){function c(){if(0<arguments.length)return c.Ka(d,arguments[0])&&(c.P(),d=arguments[0],c.O()),this;a.k.zb(c);return d}var d=b;a.N.call(c);a.a.sa(c,a.m.fn);c.o=function(){return d};c.O=function(){c.notifySubscribers(d)};c.P=function(){c.notifySubscribers(d,"beforeChange")};a.s(c,"peek",c.o);a.s(c,"valueHasMutated",c.O);a.s(c,"valueWillMutate",c.P);return c}

回想一下,在 if 语句中写一个更好的东西是

if (!that.name())

我们调用函数来获取值。 ''undefined 都是 falsey in javascript,因此 if 语句将捕获这两种情况并退出,这正是我们想要的。请注意,如果 name 的值为 0 或任何其他 falsey javascript 值,它也会退出。

This api call returns a JSON object with a nested object inside. What I want, is to display the keys and values from the nested object as li's on the view. Right now I can't even get it to tell me if its actually grabbing the object in the first place.

您的观点有很多问题。

<ul data-bind="foreach: name">

这将遍历 that.name 的值。如果 that.name'ryebrush',这将(我相信)遍历每个字母。那可不行。如果您的目标是 that.name 中的召唤师列表,则需要将 ko.observable 替换为 ko.observableArray。您可能还想将名称 that.name 更改为 that.names 以避免混淆。

<li data-bind="text:$data"></li>

这是正确的如果您的数组中充满了字符串。 foreach会遍历数组中的每一项,$data就是每一项。但是,如果该项目实际上是一个对象,您可以引用该项目的属性。例如,如果数组中的每个项目是 {"id":25500750,"name":"RyeBrush","profileIconId":551,"summonerLevel":30,"revisionDate":1426533699000}

然后,由于名称是对象上的 属性,您可以在视图中引用 name

<li data-bind="text:name"></li>

最后,您在 http 调用后实际上并没有在正确的位置获取数据。如果对您的 http 调用的响应是

{"ryebrush":{"id":25500750,"name":"RyeBrush","profileIconId":551,"summonerLevel":30,"revisionDate":1426533699000}}

那么你会想写

return http.jsonp(url + name + key, 'jsoncallback')
    .then(function(response){
        that.name(response["ryebrush"]);
    });

如果响应是项目数组

[{"ryebrush":{"id":25500750,"name":"RyeBrush","profileIconId":551,"summonerLevel":30,"revisionDate":1426533699000}}]

那么你会想写

return http.jsonp(url + name + key, 'jsoncallback')
    .then(function(response){
        that.name(response[0]["ryebrush"]);
    });

结论

不幸的是,这不是一个很好的问题。我不能确切地说出你正在使用的 API 发生了什么,所以我不能确切地告诉你你应该写什么。要完成您想要做的事情,您需要花一点时间阅读 javascript、knockout、 durandal。这里有一些很好的资源:

但是,我发现您是新用户。我想鼓励你不要气馁。学习绳索需要一些时间,但这是值得的。不要放弃。希望对您有所帮助!