Javascript Ember CLI-重新适应第三方API

Javascript Ember CLI-重新适应第三方API,javascript,ember.js,ember-data,tumblr,ember-cli,Javascript,Ember.js,Ember Data,Tumblr,Ember Cli,我可以使用ic.ajax将数据输入我的应用程序,但似乎我应该使用RESTAdapter。解释是如此简单,以至于我不知道在各种情况下该怎么办。这是我认为应该起作用的:(并与fixture、本地express服务器和http mock一起使用) 我将以tumblr为例,因为它通常是友好的API 路由器.js routes/post.js 所以,据我所知-find()是一个神奇的ajax调用。。。但是如果我想指定jsonp或其他什么呢 适配器/post.js 这有点奇怪,因为tumblr端点太长了——

我可以使用ic.ajax将数据输入我的应用程序,但似乎我应该使用RESTAdapter。解释是如此简单,以至于我不知道在各种情况下该怎么办。这是我认为应该起作用的:(并与fixture、本地express服务器和http mock一起使用)

我将以tumblr为例,因为它通常是友好的API

路由器.js routes/post.js 所以,据我所知-
find()
是一个神奇的ajax调用。。。但是如果我想指定jsonp或其他什么呢

适配器/post.js 这有点奇怪,因为tumblr端点太长了——我觉得应该是
http://api.tumblr.com
也许还有另一种方法来指定其他内容。。。或者它只是不知怎的知道。。。非常困惑。。。似乎名称空间:“v2”是该选项的用途

模板/帖子.hbs 然后在这之上-我得到了一个似乎是cors问题的
gethttp://api.tumblr.com/v2/blog/feministlibraryonwheels.tumblr.com/posts?api_key=UbB4p0GxqNa6wUa8VwpIdqtywjIiA6vljZXyI9wkx9hnQnAFyk/posts 401(未授权)

而且它并不是真的隐藏着。。。[

许多快速教程(以及现实世界中的RestaAdapter)与real API之间缺少的链接是什么???任何方向都将非常感谢。 此外,这里还有一些
ic.ajax()
尝试。有效负载到达控制台-但在尝试将数据放入模板时,它变得模糊

import Ember from 'ember';
import ajax from 'ic-ajax';

export default Ember.Route.extend({

  model: function() {
    var libraryData = ajax({
      url: 'http://www.librarything.com/api_getdata.php?userid=F.L.O.W.&showstructure=1&showTags=1&booksort=title_REV',
      type: 'get',
      dataType: 'jsonp'
    });
    console.log(libraryData);
    return libraryData;
  }

});



编辑:2.4文档非常棒。Ember数据非常稳定。如果不是JSON API格式,你需要知道你得到的是什么类型的JSON,然后你需要序列化数据并将其转化为该格式。

tumblr虽然看起来是一个友好的API,但实际上对Ember不太友好。Ember数据需要一种非常特定的JSON格式,而我如果答案不匹配,它就不会像许多简化教程那样“神奇”或“有效”

查找功能:

您的做法是正确的(定义自定义适配器)。您可以研究在适配器内重写buildURL

阅读并了解有关如何将传入的json转换为Ember喜欢的表单的更多详细信息

如果你放了一个jsbin,我可以看一看。

更新,以及以上内容 工具(适配器和序列化程序)

要连接到一个不支持Ember数据的API(比如tumblr),您必须正确地构建请求,比如or

(JSONAPIAdapter是RESTAdapter的一个子类,它调整JSON API的一些内容,例如规范所需的
Accept:application/vnd.API+JSON
头)

此外,如果检索到的数据不符合格式,则应选择最合适的序列化程序对后端返回的数据进行格式化和处理,例如,或。以下是这3个序列化程序的简短摘要:

JSONSerializer

  • 基本序列化程序(扩展抽象DS.serializer)
  • 提供规范化钩子来处理接收到的数据
  • 提供序列化钩子来处理发送的数据
  • 需要通常的JSON格式

    { "id": 1, "name": "Bob", "friends": [array of friend ids], "links": { "home": "/bobshome" } } 在
    路线中的用法

    // ...
    model() {
        return this.store.findRecord('blog', 'mynameisbob');
    }
    // ...
    
    但是,有多种方法可以实现这一点。您还可以将api密钥和主机url存储为适配器的属性,并仅使用它们来构建url(使用挂钩):

    对于与Github API通信的简单Ember应用程序

    社区驱动适配器作为示例:

    一些有用的阅读资料:


    余烬前1.13.0 下面是一个关于如何编写自定义的简单示例。本质上,您需要做的是覆盖所需的商店查找挂钩(
    find
    findAll
    findQuery
    ),以及
    buildURL()

    因为它是一个外部API,我们需要担心CORS,所以我们还应该重写
    ajax
    hook

    自定义Tumblr适配器:

    App.TumblrAdapter = DS.RESTAdapter.extend({
    
        buildURL: function(type, id, record) {
            var tumblrBlogName = 'feministlibraryonwheels';
            var tumblrApiKey = 'abcdefg';
            var tumblrRequestUrl = 'http://api.tumblr.com/v2/blog/' + tumblrBlogName + '.tumblr.com' + '/posts?api_key=' + tumblrApiKey;
            return tumblrRequestUrl;
        },
    
        ajax: function(url, method, hash) {
            hash = hash || {};                         // hash may be undefined
            hash.crossDomain = true;                   // make it CORS
            hash.xhrFields = {withCredentials: true};
            return this._super(url, method, hash);
        },
    
        find: function(store, type, id, record) {
           // customization here or within buildURL
           return this.ajax(this.buildURL(), 'GET');
        },
    
        findAll: function(store, type, sinceToken) {
            // customization here or within buildURL
            return this.ajax(this.buildURL(), 'GET');
        },
    
        findQuery: function(store, type, query) {
            // customization here or within buildURL
            return this.ajax(this.buildURL(), 'GET');
        },
    
        findMany: function(store, type, ids, owner) {
            // customization here or within buildURL
            return this.ajax(this.buildURL(), 'GET');
        }
    });
    
    如果响应没有正确格式化为余烬数据,我们可以在
    ajax
    hook中快速修复它,只需一个简单的承诺:

    ajax: function(url, method, hash) {
        hash = hash || {};                         // hash may be undefined
        hash.crossDomain = true;                   // make it CORS
        hash.xhrFields = {withCredentials: true};
        return this._super(url, method, hash).then(function(json) {
            // Massage data to look like RESTAdapter expects.
            return { tumblrs: [json] };
        });
    },
    
    如果您希望正确地定义所有具有关系的模型,则需要实现一个定制来正确地传递数据

    这是我自己在研究这些东西时遇到的一个问题。

    使用Ember 1.13.3

    特别是关于Tumblr,我在adapters/post.js中有以下内容

    import DS from "ember-data";
    
    export default DS.RESTAdapter.extend({
        host: 'https://api.tumblr.com',
        namespace: 'v2/blog/example.tumblr.com',
        apiKey: 'example',
    
        ajaxOptions() {
            var hash = this._super.apply(this, arguments);
            hash.data = hash.data || {};
            hash.data.api_key = this.get('apiKey');
            hash.dataType = 'jsonp';
            return hash;
        }
    });
    

    CLI的一部分是文件约定。在jsbin中,你能拥有完整的CLI环境吗?不,但是如果你用mockjax发布它,可能会更容易得到别人的帮助,在这一点上,你自己可以将它转换回CLI试图理解这一点。谢谢你的帮助。我知道你用了简单这个词3次,但我想这是主观的。LOL.@sHerifderek哈哈,我知道,我花了一些时间来掌握这些东西,如果你需要我澄清一些事情,请告诉我,但你确实需要彻底阅读余烬文档,特别是RESTAdapther和RESTSerializer的API页面,其中解释了所有这些方法 { "id": 1, "name": "Bob", "friends": [array of friend ids], "links": { "home": "/bobshome" } } { "user": { "id": 1, "name": "Bob", "friends": [array of friend ids], "links": { "home": "/bobshome" } } }
    export default DS.RESTAdapter.extend({
        namespace: 'v2/blog/',           // https://guides.emberjs.com/v2.0.0/models/customizing-adapters/#toc_endpoint-path-customization
        host: 'https://api.tumblr.com',  // https://guides.emberjs.com/v2.0.0/models/customizing-adapters/#toc_host-customization
        headers: {                       // https://guides.emberjs.com/v2.0.0/models/customizing-adapters/#toc_headers-customization
            'api_key': 'abcdefg'
        }
    
        // set any default ajax options you might need
        ajaxOptions(url, type, options = {}) {
            options.crossDomain = true;                   // make it CORS
            options.dataType = 'jsonp';
            return this._super(url, type, options);
        }
    
        // find a blog
        findRecord: function(store, type, id, snapshot) {
            const URL = this.buildURL(type.modelName, id, snapshot, 'findRecord');
            return this.ajax(URL, 'GET');
        }
    });
    
    // ...
    model() {
        return this.store.findRecord('blog', 'mynameisbob');
    }
    // ...
    
    export default DS.RESTAdapter.extend({
        hostUrl: 'https://api.tumblr.com/v2/blog'
        apiKey: 'abcdefg',
    
        buildURL: function(modelName, id, snapshot, requestType, query) {
            // customize the url based on the parameters
            // lets assume the id is the blog name
            return `${this.get('hostUrl')}/${id}.tumblr.com/posts?api_key=${this.get('apiKey')}`;
        }
    
        // find a blog
        findRecord: function(store, type, id, snapshot) {
            const URL = this.buildURL(type.modelName, id, snapshot, 'findRecord');
            return this.ajax(URL, 'GET');
        }
    });
    
    App.TumblrAdapter = DS.RESTAdapter.extend({
    
        buildURL: function(type, id, record) {
            var tumblrBlogName = 'feministlibraryonwheels';
            var tumblrApiKey = 'abcdefg';
            var tumblrRequestUrl = 'http://api.tumblr.com/v2/blog/' + tumblrBlogName + '.tumblr.com' + '/posts?api_key=' + tumblrApiKey;
            return tumblrRequestUrl;
        },
    
        ajax: function(url, method, hash) {
            hash = hash || {};                         // hash may be undefined
            hash.crossDomain = true;                   // make it CORS
            hash.xhrFields = {withCredentials: true};
            return this._super(url, method, hash);
        },
    
        find: function(store, type, id, record) {
           // customization here or within buildURL
           return this.ajax(this.buildURL(), 'GET');
        },
    
        findAll: function(store, type, sinceToken) {
            // customization here or within buildURL
            return this.ajax(this.buildURL(), 'GET');
        },
    
        findQuery: function(store, type, query) {
            // customization here or within buildURL
            return this.ajax(this.buildURL(), 'GET');
        },
    
        findMany: function(store, type, ids, owner) {
            // customization here or within buildURL
            return this.ajax(this.buildURL(), 'GET');
        }
    });
    
    ajax: function(url, method, hash) {
        hash = hash || {};                         // hash may be undefined
        hash.crossDomain = true;                   // make it CORS
        hash.xhrFields = {withCredentials: true};
        return this._super(url, method, hash).then(function(json) {
            // Massage data to look like RESTAdapter expects.
            return { tumblrs: [json] };
        });
    },
    
    import DS from "ember-data";
    
    export default DS.RESTAdapter.extend({
        host: 'https://api.tumblr.com',
        namespace: 'v2/blog/example.tumblr.com',
        apiKey: 'example',
    
        ajaxOptions() {
            var hash = this._super.apply(this, arguments);
            hash.data = hash.data || {};
            hash.data.api_key = this.get('apiKey');
            hash.dataType = 'jsonp';
            return hash;
        }
    });