基于 API驱动的 Web APP 的 JavaScript 连接二





接下来的程序代码如下图所示:


if ( regUrl.test(this.userInput) && regId.test(this.userInput) ) {
    this.userInputIsValid = true;
    var id = regId.exec(this.userInput);
    this.appId = id[1];
} else {
    this.userInputIsValid = false;
    this.appId = '';
}


.test() 方法在正则表达式的语义里表明是去寻找那指定的字串,并且根据制定的校验规则,确定返回来的是真还是假。 在我们的这个实现方法里面, 我们是通过 regUrl以及 regID两个参数来进行判断的,判断用户所输入的链接是否以 http://itunes开头,以及该字串里面是否包含了/id这个字禾人土日。

如果这两个条件都满足了,程序就会设置userInputValid为真,并帮助我们把该链接里的 ID提取出来,赋值给 appId. 要完成这些,我们就得在输入之后调用 .exec() 方法。该运行的结果就会返回两个条目的数组:一个就是完全满足的正则表达式,另一个就是把/id后面的字串抽取出来的子字串(只所以能完成这个就是因为在括号里面的 (/d+)参数会告诉程序:记住每一个在这里获得的数字。)所以如果这里调用了.exec()方法,您所应该得到的字串就应该象这样式的:[“/id12345”, “12345” ]. 而对于我们来说,只要第二种字串即可,所以我们就把第二个参数赋值给 appId 去完成接下来的任务。

如果两个校验返回来的为假,那么我们就给userInputIsValid 设置为无效,同时appId也会保持为一个空字串。

现在校验用户的输入是否有效这个功能已经准备好了。所以我们可以继续我们更多的脚本工作了。


抛出错误


现在我们所在的程序节点恰恰就是决定告诉用户,他所输入是正确的还是错误的,所以我们应该在程序里加上如下的代码:


if( Gimmie.userInputIsValid ) {
    /* make API request */
} else {
    /* throw an error */
}


好了,现在可以开始处理 抛出错误 的部分了。应该在程序运行的过程中,有可能因为各种意想不到的情况,让程序产生错误,所以我们应该在程序里面做出一个程序出错的处理机制,根据出错的大致类型,给用户展示相关的错误信息。 回忆下,我们到时在 sketch里面所设计的样式应该是这样的:

一般出错信息的展示方式包括这两部分:错误标题就是一个纯文本,另外一个就是错误的信息体根据出错的类型展示不同的错误信息。所以我们就得写一段通过出错信息处理代码来接受这两部分。标题主要是描述错误,信息体主要是讲述错误如何产生,以及如何修复。对于指定的例子,比方对于客户的无效输入,我们需要特别通知一下客户,什么才是正确的输入。所以我们现在就根据传递的参数来写这段错误信息代码吧:

if( Gimmie.userInputIsValid ) {
    /* make API request */
} else {
    Gimmie.throwError(
        'Invalid Link',
        'You must submit a standard iTunes store link with an ID, i.e. https://itunes.apple.com/us/app/twitter/id333903271?mt=8'
    );
}


这里,我们主要是调用gimmie.throwError() 函数,并且给该函数传递两个参数:错误标题,以及错误的信息体。 如果愿意,我们可以直接在这些参数里面就包装好html的元素。在我们的这个例子里面,在出错的信息内容里我们把包含的iTunes的链接信息用 标签重点强调给用户看看,然后提示他们:“嗨,我们所需要的是iTunes 商品的链接,您也一定要确定链接里面包含了应用的 ID.

您可以通过 CSS文件来强调 标签内的强调内容,就比如在这里我们给出错信息内容加上颜色:

.content--error {
    color: #196E76;
}
.content em {
    font-style: normal;
    background-color: lightyellow;
}


现在,您就可以在Gimmie对象写 throwError 函数的代码了:

var Gimmie = {
    /* prior code here */
    throwError: function(header, text){
        this.$content
            .html('

' + header + ' ' + text + '

') .addClass('content--error'); this.toggleLoading(); } }


注意到我们已经获得了 this.$content. 这里也可以写成 $(‘.content’) 来获取选择的值。但我们要把所选择的内容做为一个变量存到了 Gimmie对象中了,是因为在这段程序里,我们要不断的用到他。所以我们在这里的引用使用的是 this.$content. 现在就可以把 HTML页面内容设置为 $content 传递过来的内容了,我们已经在页头的样式表里把文字样式设置成为加粗显示了,所以这里要新加一个字体样式以显示我们想给出错信息设置的字体形式,这个字体形式类为:content-error. 最后,再次调用 toggleLoading()函数清除掉加载类,并且不再显示加载图标了。

到现阶段,如果您在程序里输入一个错误的 URL, 比方: http://www.bjunionstar.net, 或者您输入的链接是用 iTunes URI 开头的,但是并不包含应用的 ID,比方: http://itunes.apple.com/us/app/优联实达. 这时用户就可以看到如下的出错信息了。

让我们再来扩展一点出错的功能,在那些支持的浏览器中,我们可以在程序抛错时加一个小的 弹出动画。 要实现这个,我们就得加载/称掉这段为文字准备的小动画样式表。把如下的代码加进CSS文件吧:

.content--error-pop {
    -webkit-animation: pop .333s;
    -moz-animation: pop .333s;
    -o-animation: pop .333s;
    animation: pop .333s;
}
 
@-webkit-keyframes pop {
    0%   {-webkit-transform: scale(1);}
    50%  {-webkit-transform: scale(1.075);}
    100% {-webkit-transform: scale(1);}
}
 
@-moz-keyframes pop {
    0%   {-webkit-transform: scale(1);}
    50%  {-webkit-transform: scale(1.075);}
    100% {-webkit-transform: scale(1);}
}
 
@-o-keyframes pop {
    0%   {-webkit-transform: scale(1);}
    50%  {-webkit-transform: scale(1.075);}
    100% {-webkit-transform: scale(1);}
}
 
@keyframes pop {
    0%   {-webkit-transform: scale(1);}
    50%  {-webkit-transform: scale(1.075);}
    100% {-webkit-transform: scale(1);}
}


这就可以让您的出错信息放大或缩小,有一个好象被弹出来的效果了。我们再用 Javascript 来控制下何时加载这段样式表,何时移除。 所以在 throwError 函数中要加上如下的代码:

throwError: function(header, text){
        // Remove animation class
        this.$content.removeClass('content--error-pop');
 
        // Trigger reflow
        // https://css-tricks.com/restart-css-animation/
        this.$content[0].offsetWidth = this.$content[0].offsetWidth;
 
        // Add classes and content
        this.$content
            .html('

' + header + ' ' + text + '

') .addClass('content--error content--error-pop'); this.toggleLoading(); },


把这些新加的代码布署好到您的应用服务器上面,测试一下如果您现在输入错误的信息,错误提示的显示是否和您预期的一样:


提交 API 请求


我们离成功越来越近了。现在我们可以检查,用户提交的链接是否正确,我们也提供了错误信息,提示用户的错误操作, 所以现在就可以正式提交 API请求了。

这段提交请求,可以直接放在 if() 的判断语句里:

if( Gimmie.userInputIsValid ) {
    $.ajax({
        url: "https://itunes.apple.com/lookup?id=" + Gimmie.appId,
        dataType: 'JSONP'
    })
    .done(function(response) {
        // when finished
    })
    .fail(function(data) {
        // when request fails
    });
} else {
    /* our other code here */
}


代码里可以看出来,我们在这里提交的是一个 AJAX 请求给 iTunes API. 还记得我们在前面提到过,iTunes API 有一个 lookup 的链接,我们可以通过点击该链接拿到想要的信息。 该返回信息是用如下的格式:http://itunes.apple.com/lookup?id=***. 后面这串数字就是您想要得到的应用的 ID API 给了我们一个 Yelp 应用的例子: https://itunes.apple.com/lookup?id=284910350. 把这个链接输入您的浏览器,会得到一段 JSON代码如下所示:


稍稍处理一下这段代码的格式,象 JSON代码一样排排版,您就会得到更容易看懂的代码如下图所示:



查看 API 的帮助文档,您会注意到该 API可以提供在iTunes商品里的各种内容的返回值:从音乐到电影到应用程序。 这对我们很有用,表明我们的这个小程序就不仅仅可以获得移动应用的图标了,同时也可以得到所有MAC系统的应用图标!Mac 系统的图标所用到的链接地址和 iOS 的应用类型是一样的。 例如: FCP 的链接如下所示: https://itunes.apple.com/us/app/final-cut-pro/id424389933?mt=12. 们很熟悉的格式了,以 http://itunes 开头, 同时里面包含该应用的 ID信息了,这些都是我们需要的。

在出错处理函数中的判断语句里面,再加上一些相关的内容,用来处理提交API请求出错的问题吧:

if( Gimmie.userInputIsValid ) {
    $.ajax({
        url: "https://itunes.apple.com/lookup?id=" + Gimmie.appId,
        dataType: 'JSONP'
    })
    .done(function(response) {
        // when finished
    })
    .fail(function(data) {
        Gimmie.throwError(
            'iTunes API Error',
            'There was an error retrieving the info. Check the iTunes URL or try again later.'
        );
    });
} else {
    /* our other code here */
}


由于我们已经把出错的问题都专门提取出来做为一个专门的函数了,所以再处理其它的出错问题就相当容易了。


响应


现在让我们开始处理当请求成功完成后,程序应该做些啥?

$.ajax({
    /* other code here */
})
.done(function(response) {
    // Get the first response and log it
    var response = response.results[0];
    console.log(response);
})
.fail(function(data) {
    /* other code here */
});


注意这里,我们得到了API 的响应,并且把第一个结果记录到控制台上。 如果您查看 API 请求的例子,就可以看到在 JSON 对象的最上面有一个参数 resultCount, 该参数表明了该对象的返回结果数量(对于我们的 lookup 方法来说,返回结果应该只有一个),同时也指明了具体是哪一个结果数组储存了我们想的返回数据(在我们的例子中,该结果也是只有一个)


根据这个我们就把该响应赋值给结果的第一个项目同时记录到控制台里。 如果您打开了我们的小应用并且输入了链接地址,比方:https://itunes.apple.com/lookup?id=284910350 您会注意到我们的程序被卡在加载状态了。此时通过查看开发者工具,并用打开控制台,您会看到 API 的响应其实是已经被记录,我们现在可以使用 JavaScript 来使用这些资源了。



如同您所见: API返回了一大堆 APP 的详细信息: 名字,开发者,描述,类别,价格,以及其它。 我们其实真正需要的很少,就是该应用的图标。 所以我们就来查看一下这些返回的信息里是否有我们需要的。

$.ajax({
    /* other code here */
})
.done(function(response) {
    // Get the first response and log it
    var response = response.results[0];
    console.log(response);
 
    // Check to see if request is valid & contains the info we want
    // If it does, render it. Otherwise throw an error
    if(response && response.artworkUrl512 != null){
        Gimmie.render(response);
    } else {
        Gimmie.throwError(
            'Invalid Response',
            'The request you made appears to not have an associated icon. 
 Try a different URL.'
        );
    }
})
.fail(function(data) {
    /* other code here */
});


仔细查看后发现:response.artworkUrl512 正是我们所需要的信息。 artworkUrl512 正是 API返回的全尺寸应用图标的关键字。既然已经得到了我们需要的信息,下一步就是把他们在页面上展示出来。 为了实现,我们需要开发另外一个函数名字叫做 render. 如果出现了一些其它异常的情况,就用我们已经开发好的出错处理机制抛出错误即可。


展示 API返回结果


我们已经拿到 API返回的结果了,就让我们把他们显示到页面上吧。 一旦我们判断出来所需要的信息都已经拿到手后,就让程序调用 Gimmie.render(response) 函数,同时把APIresponse 参数传递过去,该参数可是包含了重要的应用程序关键字。 所以返回到 Gimmie 对象, 开始创建 render 函数吧。

var Gimmie = {
    /* our other code here */
    render: function(response){
        var icon = new Image();
        icon.src = response.artworkUrl512;
        icon.onload = function() {
            Gimmie.$content
                .html(this)
                .append('

' + response.trackName + '

') .removeClass('content--error'); Gimmie.toggleLoading(); } } }


这段代码中,我们主要做如下工作:

  • 从头开始构造一个图像类,我们创造一个变量名字为 icon, 同时调用了用来创建 HTMLImageElement Image()构造器。考虑他就象使用 JavaScript 脚本文件在内存中创建.

  • 利用 Image()构造器的icon.scr 方法给我们的图像设置src 属性,然后把我们从 API 响应中拿到的图片地址信息: artworkUrl512 赋值给 src属性。这就可以告诉浏览器到指定的位置去拿该图标。

  • 我们使用 icon.onload 方法告诉浏览器,当完成了图像抓取工作后,应该做这个了。。这种方法可以保证浏览器在完成了所有图片抓取工作以后,才把图象文件真正的放进文档对象模型中。

  • icon.onload 里面我们给 HTML的标签 $contents 设置为刚刚得到的图片文件。 同时也可以添加更多的您想在这个区域展示的信息。 在这个例子中,我从 API的响应中获得了 trackName,所以就会在这个地方和图标一起把应用的名字也展示出来。

  • 最后执行 toggleLoading 函数,因为我们已经加载了所有的东西。

打开应用,输入示例的链接地址:https://itunes.apple.com/us/app/yelp/id284910350?mt=8 您就会得到一个很漂亮的图标文件在浏览器里。


再试一个Mac 系统的应用,比方Final Cut Pro吧: https://itunes.apple.com/us/app/final-cut-pro/id424389933?mt=12



加载图标蒙板


现在应用里面加载的图标并不是圆角的。 我们在前面早已经提过了,大部分的iOS图标并不是在设计的时候就做成了圆角。 这个效果是在应用的操作系统级别实现的。对于 iOS的图标来说,我们得把之前在 sketch中创建的蒙板效果加上去。 所以您先回到sketch项目中,把当时设计的蒙版文件输出来,放进我们的系统中,以备系统在加载图标的时候,可以在上面加上该蒙版。

var Gimmie = {
    render: function(response){
        var icon = new Image();
        icon.src = response.artworkUrl512;
        icon.onload = function() {
            Gimmie.$content
                .html(this)
                .append('

' + response.trackName + ' Actual icon dimensions: ' + this.naturalWidth + '×' + this.naturalHeight + '

') .removeClass('content--error'); Gimmie.toggleLoading(); // If it's an iOS icon, load the mask too if(response.kind != 'mac-software') { var mask = new Image(); mask.src = 'assets/img/icon-mask.png'; mask.onload = function() { Gimmie.$content.prepend(this); } } } } }


我们做了如下的工作:


  • API的结果集里,有一个叫做 kind 的对象,该对象标明的从API返回的结果的类型,比方是电影,音乐还是软件。 Mac 应用的 kind值应该是: mac-software. 因为 Mac 应用不需要圆角蒙版,所以我们得检查一下,如果响应里的类型属性为非 mac-software的,才需要加载蒙版。

  • 这里也要调用同一个 Image()构造器,我们在前面加载图标的时候已经用过了。在这里我们把src设置为蒙版的图片,提前把这个图片加载到系统中,等加载程序加好了我们所要图标的时候一起使用。

现在我们再把下面的代码加到 CSS文件里面为该蒙版指定样式。

.content img[src*="icon-mask.png"] {
    position: absolute;
    left: 0;
    top: 0;
}


终于完成了。再试一次输入Yelp 链接地址,这次就会出现如你所想的带圆角的应用程序图标了。


完成


这一过程还挺长,我是真心希望您在这里学到了些东西。我们在不同的阶段创造了不同东西,包括设计的线框图到不同的模型。 我们也谈到用HTML, CSS 以及 Javascript 一起来开发 web App, 以实现该应用和第三方API的交互。

希望您已经领会了API交互的精髓。 您已经学会了如何动态从第三方的 API拿到相应的资料,并把他展示在网页上。 基于这个基础,您可以真正的开始针对您所感兴趣的应用程序大展拳脚了。

下面我列出一些有可能对您有帮助的第三方就算程序的API:


本系列完!

不深思则不能造于道。不深思而得者,其得易失。

名人名言- 曾国藩
  • By 优联实达(译)
  • 2015-10-14
  • 3294
  • 公司新闻,网站开发,网站设计,UI