如何将外部API中的其他数据添加到集合中的现有模型?

时间:2013-10-22 08:49:40

标签: javascript ajax backbone.js coffeescript

我在开发服务器上本地运行一个基本的REST API,后面有一个sqlite数据库。我的模型有两个属性。年份和头衔。基于这两个属性,我想通过每个模型的AJAX调用从外部公共API获取其他数据,但不希望将其他数据存储在我的本地数据库中。我怎样才能做到这一点?覆盖集合的获取方法?

对于递归AJAX调用的改进也将受到赞赏......

谢谢

代码:

class window.Movie extends Backbone.Model
    initialize: ->
        @fetchData()

    fetchData: ->
        api_url = "api_url"
        api_key = "api_key"
        model   = @
        year    = model.get "year"
        title   = model.get "title"

        $.get "#{api_url}/configuration?api_key=#{api_key}", (data) ->
            model.set "base_url", data.images.base_url

            $.get "#{api_url}/search/movie?api_key=#{api_key}&query=#{title}&include_adult=false&year=#{year}", (data) ->
                q_id = data.results[0].id

                $.get "#{api_url}/movie/#{q_id}?api_key=#{api_key}", (data) ->
                    model.set "poster_path", data.poster_path

class window.Movies extends Backbone.Collection
    model: Movie
    url: "/api/movies"

1 个答案:

答案 0 :(得分:1)

据我了解您的问题,您希望使用其他API中的其他数据来装饰您的模型。我认为最好的方法是实现您自己的Backbone.sync版本:

  

Backbone.sync是Backbone每次尝试读取模型或将模型保存到服务器时调用的函数。默认情况下,它使用jQuery.ajax发出RESTful JSON请求并返回jqXHR。您可以覆盖它以使用不同的持久性策略,例如WebSockets,XML传输或本地存储。

     

Backbone.sync的方法签名是sync(method, model, [options])

     
      
  • 方法 - CRUD方法("create""read""update""delete"
  •   
  • model - 要保存的模型(或要读取的集合)
  •   
  • 选项 - 成功和错误回调以及所有其他jQuery请求选项
  •   

此外:

  

同步功能可以全局覆盖为Backbone.sync,或者通过向Backbone集合或单个模型添加sync函数,以更细粒度的级别覆盖。

     

默认同步处理程序将CRUD映射到REST,如下所示:

     
      
  • 创建→发布/collection
  •   
  • 阅读→获取/collection[/id]
  •   
  • 更新→PUT /collection/id
  •   
  • 删除→删除/collection/id
  •   

因此,您应该能够实现sync函数,该函数首先使用默认的Backbone.sync从API获取数据,然后使用外部API中的数据对其进行修饰。

要处理三个GET,您可以使用async,例如:

getConfig = (next) ->

  $.get "#{api_url}/configuration?api_key=#{api_key}", next

findMovie = (next) ->

  $.get "#{api_url}/search/movie?api_key=#{api_key}&query=#{title}&include_adult=false&year=#{year}", next

async.parallel [getConfig, findMovie], (err, [config, movie]) ->

  $.get "#{api_url}/movie/#{movie.results[0].id}?api_key=#{api_key}", (data) ->
    model.set "base_url", config.images.base_url
    model.set "poster_path", data.poster_path

修改:另一种可能性就是让另一个模型,比如MovieData,其URL指向此外部API。这也可能是一种更清晰的方式来利用Backbone。