zoukankan      html  css  js  c++  java
  • Backbone的localStorage.js源码详细分析

    Backbone.localStorage.js是将数据存储到游览器客户端本地的(当没有服务器的情况下)

    地址:https://github.com/jeromegn/Backbone.localStorage

    1     整个函数是一个自执行函数,简化版形式如下

    (function(a,fn) {

    //...

    })(a,fn);

    2     9-12行/**---------此处是判断上下文有没有引入AMD模块(如requirejs)-----------*/

    if(typeofdefine==="function"&&define.amd) {

    // AMD. Register as an anonymous module.

    define(["underscore","backbone"],function(_, Backbone) {

    // Use global variables if the locals are undefined.

    returnfactory(_ || root._, Backbone || root.Backbone);

    });

    }else{

    // RequireJS isn't being used. Assume underscore and backbone are loaded in script tags

    factory(_,Backbone);

    }

    此种判断方法比较常见,类似的如 toastr.js种

    typeofdefine==='function'&&define.amd?define:function(deps, factory) {

    if(typeofmodule!=='undefined'&&module.exports) {//Node

    module.exports= factory(require('jquery'));

    }else{

    window['toastr'] = factory(window['jQuery']);

    }

    }

    /**
     * Backbone localStorage Adapter
     * Version 1.1.0
     *
     * https://github.com/jeromegn/Backbone.localStorage
     */
    (function (root, factory) {
    
      /**---------此处是判断上下文有没有引入AMD模块(如requirejs)-----------*/
       if (typeof define === "function" && define.amd) {
          // AMD. Register as an anonymous module.
          define(["underscore","backbone"], function(_, Backbone) {
            // Use global variables if the locals are undefined.
            return factory(_ || root._, Backbone || root.Backbone);
          });
       } else {
          // RequireJS isn't being used. Assume underscore and backbone are loaded in script tags
          factory(_, Backbone);
       }
    }(this, function(_, Backbone) {
    // A simple module to replace `Backbone.sync` with *localStorage*-based
    // persistence. Models are given GUIDS, and saved into a JSON object. Simple
    // as that.
    
    // Hold reference to Underscore.js and Backbone.js in the closure in order
    // to make things work even if they are removed from the global namespace
    
    // Generate four random hex digits.
    function S4() {
       return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
    };
    
    // Generate a pseudo-GUID by concatenating random hexadecimal.
    // /**---------此处生成随机数  如 d9ab5797-9773-9bcd-27b1-9f23a3170957-----------*/
    function guid() {
       return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());
    };
    
    // Our Store is represented by a single JS object in *localStorage*. Create it
    // with a meaningful name, like the name you'd give a table.
    // window.Store is deprecated, use Backbone.LocalStorage instead
      /**---------定义LocalStorage函数-----------*/
    Backbone.LocalStorage = window.Store = function(name) {
      this.name = name;
      var store = this.localStorage().getItem(this.name);
      this.records = (store && store.split(",")) || [];
    };
      /**---------扩展LocalStorage函数 的 增删改查 等其他方法-----------*/
    _.extend(Backbone.LocalStorage.prototype, {
    
      // Save the current state of the **Store** to *localStorage*.
      save: function() {
        this.localStorage().setItem(this.name, this.records.join(","));
      },
    
      // Add a model, giving it a (hopefully)-unique GUID, if it doesn't already
      // have an id of it's own.
      create: function(model) {
        if (!model.id) {
          model.id = guid();//生成唯一id
          model.set(model.idAttribute, model.id);//给模型添加一条新属性id
        }
        this.localStorage().setItem(this.name+"-"+model.id, JSON.stringify(model));//setItem为原生localstorage的方法,此处是真正的把数据存储到客户端
        this.records.push(model.id.toString());
        this.save();
        return this.find(model);
      },
    
      // Update a model by replacing its copy in `this.data`.
      update: function(model) {
        this.localStorage().setItem(this.name+"-"+model.id, JSON.stringify(model));
        if (!_.include(this.records, model.id.toString()))
          this.records.push(model.id.toString()); this.save();
        return this.find(model);
      },
    
      // Retrieve a model from `this.data` by id.
      find: function(model) {
        return this.jsonData(this.localStorage().getItem(this.name+"-"+model.id));
      },
    
      // Return the array of all models currently in storage.
      findAll: function() {
        return _(this.records).chain()
          .map(function(id){
            return this.jsonData(this.localStorage().getItem(this.name+"-"+id));
          }, this)
          .compact()
          .value();
      },
    
      // Delete a model from `this.data`, returning it.
      destroy: function(model) {
        if (model.isNew())
          return false
        this.localStorage().removeItem(this.name+"-"+model.id);
        this.records = _.reject(this.records, function(id){
          return id === model.id.toString();
        });
        this.save();
        return model;
      },
    
      localStorage: function() {
        return localStorage;//返回原生的localStorage
      },
    
      // fix for "illegal access" error on Android when JSON.parse is passed null
      jsonData: function (data) {
          return data && JSON.parse(data);
      }
    
    });
    
    // localSync delegate to the model or collection's
    // *localStorage* property, which should be an instance of `Store`.
    // window.Store.sync and Backbone.localSync is deprectated, use Backbone.LocalStorage.sync instead
    Backbone.LocalStorage.sync = window.Store.sync = Backbone.localSync = function(method, model, options) {
      var store = model.localStorage || model.collection.localStorage;
    
      var resp, errorMessage, syncDfd = $.Deferred && $.Deferred(); //If $ is having Deferred - use it.//生成query的Deferred对象
      //此处是一个较大的知识点,就是promise规范,和jquery的deferred 和promise 此处不展开
    
      try {
    
        switch (method) {
          case "read":
            resp = model.id != undefined ? store.find(model) : store.findAll();
            break;
          case "create":
            resp = store.create(model);
            break;
          case "update":
            resp = store.update(model);
            break;
          case "delete":
            resp = store.destroy(model);
            break;
        }
    
      } catch(error) {
        if (error.code === DOMException.QUOTA_EXCEEDED_ERR && window.localStorage.length === 0)
          errorMessage = "Private browsing is unsupported";
        else
          errorMessage = error.message;
      }
    
      if (resp) {
        model.trigger("sync", model, resp, options);
        if (options && options.success)
          options.success(resp);
        if (syncDfd)
          syncDfd.resolve(resp);//回掉状态改为成功
    
      } else {
        errorMessage = errorMessage ? errorMessage
                                    : "Record Not Found";
    
        if (options && options.error)
          options.error(errorMessage);
        if (syncDfd)
          syncDfd.reject(errorMessage);//回掉状态改为失败
      }
    
      // add compatibility with $.ajax
      // always execute callback for success and error
      if (options && options.complete) options.complete(resp);
    
      return syncDfd && syncDfd.promise();
    };
      /**---------保存原来的sync-----------*/
    Backbone.ajaxSync = Backbone.sync;
    
      /**---------此处来判断返回哪个函数,用localstorage还是发送ajax-----------*/
    Backbone.getSyncMethod = function(model) {
      if(model.localStorage || (model.collection && model.collection.localStorage)) {
        return Backbone.localSync;
      }
    
      return Backbone.ajaxSync;
    };
    
    // Override 'Backbone.sync' to default to localSync,
    // the original 'Backbone.sync' is still available in 'Backbone.ajaxSync'
      /**---------覆盖Backbone的sync,因为原来的已经保存-----------*/
    Backbone.sync = function(method, model, options) {
      return Backbone.getSyncMethod(model).apply(this, [method, model, options]);
      //注意:Backbone.getSyncMethod(model)返回的是一个函数,再apply(),才执行返回的这个函数
    };
    
    return Backbone.LocalStorage;
    }));
  • 相关阅读:
    在Centos 7下编译openwrt+njit-client
    开博随笔
    Chapter 6. Statements
    Chapter 4. Arrays and Pointers
    Chapter 3. Library Types
    Chapter 2.  Variables and Basic Types
    关于stm32不常用的中断,如何添加, 比如timer10 timer11等
    keil 报错 expected an identifier
    案例分析 串口的地不要接到电源上 会烧掉
    案例分析 CAN OPEN 调试记录 进度
  • 原文地址:https://www.cnblogs.com/WhiteHorseIsNotHorse/p/6368309.html
Copyright © 2011-2022 走看看