国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

花了十天時(shí)間做了一個(gè)App,取名一麻貸,想著一麻袋一麻袋的放款,但是……

Miracle / 2193人閱讀

摘要:這樣里面最主要是使用一個(gè)方法,這個(gè)方法是以數(shù)據(jù)向服務(wù)器發(fā)送請(qǐng)求,然后返回一個(gè)的。

項(xiàng)目地址(http://sack.doraemoney.com)

6月14號(hào),和另外兩個(gè)同事商量著不能再像最近這幾個(gè)月這樣了,似乎每一個(gè)公司的產(chǎn)品經(jīng)理與碼農(nóng)們都是死對(duì)頭,我也沒有逃出這個(gè)怪圈,每天在對(duì)產(chǎn)品的“精雕細(xì)琢”中,讓我對(duì)產(chǎn)品越發(fā)的反感,不經(jīng)意間,看了看自己的 Git Commits List,好長(zhǎng)啊,每天都有好多,然后就想著看看自己的干了些什么,突然之間,發(fā)現(xiàn)這就是一個(gè)循環(huán)啊,基本上是下面這樣的:

for var keepGoing = true; keepGoing  {
    // 4B中
}

不行啊,我們得自己整一個(gè),但是不能在上班時(shí)間整,因?yàn)檫@是一個(gè)只有我們參與的事情,而且也不希望他人對(duì)我們的指指點(diǎn)點(diǎn),所以,決定每天的空余時(shí)間抽出幾個(gè)小時(shí),計(jì)劃著一個(gè)星期之內(nèi)整一個(gè)新的東西出來,恩,是的,App,最后還是花了我們3個(gè)人十天的時(shí)間。

這還是一個(gè)借款給有需要的人的App,沒有風(fēng)控模型,但是我們有完善的催債模型和真實(shí)性模型,我們只做一件事情,讓借款給你的人更快的相信你在按時(shí)還款,所以,我們選擇了通訊錄、通話記錄、地理位置、手機(jī)型號(hào)等這些通過一個(gè)App能快速獲取到的數(shù)據(jù)。

然后我們開始了規(guī)劃,簡(jiǎn)單的設(shè)計(jì),接口的定義以及數(shù)據(jù)結(jié)構(gòu)的定義,這花了一天的時(shí)間,我們按著花了三天時(shí)間把整個(gè)系統(tǒng)開發(fā)完了,也就是所有的功能都有了,接著花了兩天時(shí)間把所有的功能接口串連上,最后再連了四天的時(shí)間測(cè)試、調(diào)試與Bug修復(fù),Ok,一個(gè)全新的App就這么出來了。

技術(shù)使用的是:

Java

Ionic

Cordova

一些必要的插件

Java

選擇Java的原因很簡(jiǎn)單,也很純粹,我們的核心業(yè)務(wù)系統(tǒng)就是Java的,為了能更快速的開發(fā),我們還是直接使用Java,這樣很多接口的代碼可以直接復(fù)制過來改改就能使用,這為我們節(jié)省了很多開發(fā)的時(shí)間。

Ionic

這個(gè)不用想,簡(jiǎn)單的App開發(fā)中的神器,有了這個(gè)東西,即使我對(duì)App開發(fā)一無所知,我也能僅使用我自己會(huì)的前端技術(shù)實(shí)現(xiàn)一個(gè)完善的App。

Cordova

這為我們的App兼容到各種平臺(tái) iOA/Andoird等提供支持。

我是怎么做的 關(guān)于本地的數(shù)據(jù)存儲(chǔ)

因?yàn)閿?shù)據(jù)量很少,所以直接使用了 LocalStorage,我自己寫了一個(gè) AngularJSLocalStorage 的數(shù)據(jù)綁定的 Angular Module,代碼如下:

javascript/**
 * 本地存儲(chǔ)
 */
app.factory("$storage", [
  "$rootScope",
  "$window",
  function(
      $rootScope,
      $window
  ){

    var webStorage = $window["localStorage"] || (console.warn("This browser does not support Web Storage!"), {}),
        storage = {
          $default: function(items) {
            for (var k in items) {
              angular.isDefined(storage[k]) || (storage[k] = items[k]);
            }

            return storage;
          },
          $reset: function(items) {
            for (var k in storage) {
              "$" === k[0] || delete storage[k];
            }

            return storage.$default(items);
          }
        },
        _laststorage,
        _debounce;

    for (var i = 0, k; i < webStorage.length; i++) {


      (k = webStorage.key(i)) && "storage-" === k.slice(0, 8) && (storage[k.slice(8)] = angular.fromJson(webStorage.getItem(k)));
    }

    _laststorage = angular.copy(storage);

    $rootScope.$watch(function() {
      _debounce || (_debounce = setTimeout(function() {
        _debounce = null;

        if (!angular.equals(storage, _laststorage)) {
          angular.forEach(storage, function(v, k) {
            angular.isDefined(v) && "$" !== k[0] && webStorage.setItem("storage-" + k, angular.toJson(v));

            delete _laststorage[k];
          });

          for (var k in _laststorage) {
            webStorage.removeItem("storage-" + k);
          }

          _laststorage = angular.copy(storage);
        }
      }, 100));
    });


    "localStorage" === "localStorage" && $window.addEventListener && $window.addEventListener("storage", function(event) {
      if ("storage-" === event.key.slice(0, 10)) {
        event.newValue ? storage[event.key.slice(10)] = angular.fromJson(event.newValue) : delete storage[event.key.slice(10)];

        _laststorage = angular.copy(storage);

        $rootScope.$apply();
      }
    });

    return storage;
  }
]);

使用起來很簡(jiǎn)單:

javascript$storage.token = "TOKEN_STRING"; // 這就會(huì)在localStorage 中存儲(chǔ)一個(gè) `key` 為 `storage-token` 而 `value` 為 `TOKEN_STRING` 的鍵值對(duì),這是一個(gè)單向存儲(chǔ)的過程,也就是我們?cè)偈止ば薷?`localStorage` 里面的值是沒有用的,`100ms` 之后就會(huì)被 `$storage.token` 的值覆蓋,這是一個(gè)更新存儲(chǔ)的時(shí)間。
數(shù)據(jù)請(qǐng)求

因?yàn)槲覀冞@邊的接口走的不是 AngularJS 的默認(rèn)請(qǐng)求方式,數(shù)據(jù)結(jié)構(gòu)為類似表單提交,所以,我還修改了 Angular 中的 $http,轉(zhuǎn)換對(duì)象為 x-www-form-urlencoded 序列代的字符串:

javascript/**
 * 配置
 */
app.config([
  "$ionicConfigProvider",
  "$logProvider",
  "$httpProvider",
  function(
      $ionicConfigProvider,
      $logProvider,
      $httpProvider
  ) {
    // .. 其它代碼
    // 開啟日志
    $logProvider.debugEnabled(true);

    /**
     * 服務(wù)器接口端要求在發(fā)起請(qǐng)求時(shí),同時(shí)發(fā)送 Content-Type 頭信息,且其值必須為: application/x-www-form-urlencoded
     * 可選添加字符編碼,在此處我默認(rèn)將編碼設(shè)置為 utf-8
     *
     * @type {string}
     */

    $httpProvider.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded;charset=utf-8";
    $httpProvider.defaults.headers.put["Content-Type"] = "application/x-www-form-urlencoded;charset=utf-8";

    /**
     * 請(qǐng)求只接受服務(wù)器端返回 JSON 數(shù)據(jù)
     * @type {string}
     */
    $httpProvider.defaults.headers.post["Accept"] = "application/json";

    /**
     * AngularJS 對(duì)默認(rèn)提交的數(shù)據(jù)結(jié)構(gòu)為 json 格式的,但是我們NiuBilitity的服務(wù)器端不能解析 JSON 數(shù)據(jù),所以
     * 我們經(jīng) x-www-form-urlencoded 的方式提交,此處將對(duì)數(shù)據(jù)進(jìn)行封裝為 foo=bar&bar=other 的方式
     * @type {*[]}
     */
    $httpProvider.defaults.transformRequest = [function(data) {
      /**
       * 轉(zhuǎn)換對(duì)象為 x-www-form-urlencoded 序列代的字符串
       * @param {Object} obj
       * @return {String}
       */
      var param = function(obj) {
        var query = "";
        var name, value, fullSubName, subName, subValue, innerObj, i;

        for (name in obj) {
          value = obj[name];

          if (value instanceof Array) {
            for (i = 0; i < value.length; ++i) {
              subValue = value[i];
              fullSubName = name + "[" + i + "]";
              innerObj = {};
              innerObj[fullSubName] = subValue;
              query += param(innerObj) + "&";
            }
          } else if (value instanceof Object) {
            for (subName in value) {
              subValue = value[subName];
              fullSubName = name + "[" + subName + "]";
              innerObj = {};
              innerObj[fullSubName] = subValue;
              query += param(innerObj) + "&";
            }
          } else if (value !== undefined && value !== null) {
            query += encodeURIComponent(name) + "="
                + encodeURIComponent(value) + "&";
          }
        }

        return query.length ? query.substr(0, query.length - 1) : query;
      };

      return angular.isObject(data) && String(data) !== "[object File]"
          ? param(data)
          : data;
    }];

  }
]);
JSON 請(qǐng)求數(shù)據(jù)結(jié)構(gòu)

我們的數(shù)據(jù)結(jié)構(gòu)是下面這樣的:

Request
json{
  "apiVersion" : "0.0.1",
  "token" : "TOKEN_STRING",
  "requestId" : "ID_STRING",
  "data" : {
    // Data goes here
  }
}
Response
json{
  "apiVersion" : "0.0.1",
  "data" : {},
  "error" : {
    "code" : ERROR_CODE_NUMBER,
    "message" : "Error Message Here",
    "errors" : [
      {
        "code" : 0,
        "message" : "",
        "location" : ""
      }
    ]
  }
}
說明

在上面的這些數(shù)據(jù)結(jié)構(gòu)中,請(qǐng)求的很好理解,響應(yīng)的 json 結(jié)構(gòu)只有三個(gè)字段, apiVersion 表示了當(dāng)前請(qǐng)求的接口版本號(hào), data 就是數(shù)據(jù)對(duì)象, error 則是錯(cuò)誤對(duì)象,一般情況下,一個(gè) error 只有 codemessage 兩個(gè)值,但是有一些情況下可能會(huì)需要提供一些額外的錯(cuò)誤信息,那么都放入了 error.errors 這個(gè)數(shù)組中。

App前端是下面這樣的判斷的:

當(dāng) errornull 時(shí),表示請(qǐng)求成功,此時(shí)從 data 中取數(shù)據(jù);

當(dāng) error 不為 null 時(shí),表示請(qǐng)求失敗,此時(shí)從 error 中取錯(cuò)誤信息,而完全不管 data ,我采取的方式是直接拋棄(其實(shí)前后端已經(jīng)約定了,所以不存在 error 不為 null 時(shí),data 中還有數(shù)據(jù)的情況出現(xiàn)。

關(guān)于 $http

我沒有直接將接口的 url 地址、$http 請(qǐng)求等暴露給 Controller,而是做了一層封裝,我叫作為 sack(也就是 App 的名稱):

javascriptapp.factory("sack", [
  "$http",
  "$q",
  "$log",
  "$location",
  "$ionicPopup",
  "$storage",
  "API_VERSION",
  "API_PROTOCOL",
  "API_HOSTNAME",
  "API_URI_MAP",
  "util",
  function(
      $http,
      $q,
      $log,
      $location,
      $ionicPopup,
      $storage,
      API_VERSION,
      API_PROTOCOL,
      API_HOSTNAME,
      API_URI_MAP,
      util
  ){
    var HTTPUnknownError = {code: -1, message: "出現(xiàn)未知錯(cuò)誤"};
    var HTTPAuthFaildError = {code: -1, message: "授權(quán)失敗"};
    var APIPanicError = {code: -1, message: "服務(wù)器端出現(xiàn)未知錯(cuò)誤"};
    var _host = API_PROTOCOL + "://" + API_HOSTNAME + "/",
        _map = API_URI_MAP,
        _apiVersion = API_VERSION,
        _token = (function(){return $storage.token;}()) ;

    setInterval(function(){
      _token = (function(){return $storage.token;}());
      //$log.info("Got Token: " + _token);
    }, 1000);

    var appendTransform = function(defaultFunc, transFunc) {
      // We can"t guarantee that the default transformation is an array
      defaultFunc = angular.isArray(defaultFunc) ? defaultFunc : [defaultFunc];

      // Append the new transformation to the defaults
      return defaultFunc.concat(transFunc);
    };

    var _prepareRequestData = function(originData) {
      originData.token = _token;
      originData.apiVersion = _apiVersion;
      originData.requestId = util.getRandomUniqueRequestId();
      return originData;
    };

    var _prepareRequestJson = function(originData) {
      return angular.toJson({
        apiVersion: _apiVersion,
        token: _token,
        requestId: util.getRandomUniqueRequestId(),
        data: originData
      });
    };

    var _getUriObject = function(uon) {
      // 若傳入的參數(shù)帶有 _host 頭
      if((typeof uon === "string" && (uon.indexOf(_host) == 0) ) || uon === "") {
        return {
          uri: uon.replace(_host, ""),
          methods: ["post"]
        };
      }

      if(typeof _map === "undefined") {
        return {
          uri: "",
          methods: ["post"]
        };
      }

      var _uon = uon.split("."),
          _ns,
          _n;

      if(_uon.length == 1) {
        return {
          uri: "",
          methods: ["post"]
        };
      }
      _ns = _uon[0];
      _n = _uon[1];

      _mod = _map[_ns];

      if(typeof _mod === "undefined") {
        return {
          uri: "",
          methods: ["post"]
        };
      }

      _uriObject = _mod[_n];

      if(typeof _uriObject === "undefined") {
        return {
          uri: "",
          methods: ["post"]
        };
      }

      return _uriObject;
    };

    var _getUri = function(uon) {
      return _getUriObject(uon).uri;
    };

    var _getUrl = function(uon) {
      return _host + _getUri(uon);
    };

    var _auth = function(uon) {
      var _uo = _getUriObject(uon),
          _authed = false;
      $log.log("Check Auth of : " + uon);
      $log.log("Is this api need auth: " + angular.toJson(_uo.needAuth));
      $log.log("Is check passed: " + angular.toJson(!(!_token && _uo.needAuth)));
      $log.log("Token is: " + _token);
      if(!_token && _uo.needAuth) {

        $ionicPopup.alert({
          title: "提示",
          subTitle: "您當(dāng)前的登錄狀態(tài)已失效,請(qǐng)重新登錄。"
        }).then(function(){
          $location.path("/sign");
        });

        $location.path("/sign");
      } else {
        _authed = true;
      }
      return _authed;
    };

    var get = function(uon) {
      return $http.get(_getUrl(uon));
    };

    var post = function(uon, data, headers) {
      var _url = _getUrl(uon),
          _data = _prepareRequestData(data);
      $log.info("========> POST START [ " + uon + " ] ========>");
      $log.log("REQUEST URL  : " + _url);
      $log.log("REQUEST DATA : " + angular.toJson(_data));

      return $http.post(_url, _data, {
        transformResponse: appendTransform($http.defaults.transformResponse, function(value) {
          $log.log("RECEIVED JSON : " + angular.toJson(value));
          if(typeof value.ex != "undefined") {
            return {
              error: APIPanicError
            };
          }
          return value;
        })
      });
    };

    var promise = function(uon, data, headers) {
      var defer = $q.defer();

      if(!_auth(uon)) {
        defer.reject(HTTPAuthFaildError);
        return defer.promise;
      }

      post(uon, data, headers).success(function(res){
        if(res.error) {
          defer.reject(res.error);
        } else {
          defer.resolve(res.data);
        }
      }).error(function(res){
        defer.reject(HTTPUnknownError);
      });
      return defer.promise;
    };

    var postJson = function(uon, data, headers) {
      var _url = _getUrl(uon),
          _json = _prepareRequestJson(data);
      $log.info("========> POST START [ " + uon + " ] ========>");
      $log.log("REQUEST URL  : " + _url);
      $log.log("REQUEST JSON : " + _json);
      return $http.post(_url, _json, {
        transformResponse: appendTransform($http.defaults.transformResponse, function(value) {
          $log.log("RECEIVED JSON : " + angular.toJson(value));
          if(typeof value.ex != "undefined") {
            return {
              error: APIPanicError
            };
          }
          return value;
        })
      });
    };

    var promiseJson = function(uon, data, headers) {
      var defer = $q.defer();

      if(!_auth(uon)) {
        defer.reject(HTTPAuthFaildError);
        return defer.promise;
      }

      postJson(uon, data, headers).success(function(res){
        if(res.error) {
          defer.reject(res.error);
        } else {
          defer.resolve(res.data);
        }
      }).error(function(res){
        defer.reject(HTTPUnknownError);
      });
      return defer.promise;
    };

    return {
      get: get,
      post: post,
      promise: promise,

      postJson: postJson,
      promiseJson: promiseJson,
      _auth: _auth,
      HTTPAuthFaildError: HTTPAuthFaildError
    };
  }
]);

這樣里面最主要是使用一個(gè)方法: sack.promiseJson,這個(gè)方法是以 json 數(shù)據(jù)向服務(wù)器發(fā)送請(qǐng)求,然后返回一個(gè) promise 的。

上面的 API_URI_MAP 的數(shù)據(jù)結(jié)構(gòu)類似于下面這樣的:

javascriptapp.constant("API_URI_MAP", {
  user : {
    sign : {
      needAuth: false,
      uri : "sack/user/sign.json",
      methods: [
        "post"
      ],
      params: {
        mobile: "string", // 手機(jī)號(hào)碼
        captcha: "string" // 驗(yàn)證碼
      }
    },
    unsign: {
      needAuth: true,
      uri: "sack/user/unsign.json",
      methods: [
        "post"
      ],
      params: {
        token: "string"
      }
    },
    //...
  }
  //...
});

然后,更具體的,在 Controller 中也不直接使用 sack.promiseJson 這個(gè)方法,而是使用封裝好的服務(wù)進(jìn)行,比如下面這個(gè)服務(wù):

javascriptapp.factory("UserService", function($rootScope, $q, $storage, API_CACHE_TIME, sack) {
  var sign = function(data) {
    return sack.promiseJson("user.sign", data);
  };

  return {
    sign: sign
  }
});

這樣的好處是,我可以直接使用類似下面這樣發(fā)起請(qǐng)求:

UserService.sign({mobile:"xxxxxxxxxxx",captcha:"000000"}).then(function(res){
  // 授權(quán)成功
}, function(err){
  // 授權(quán)失敗
});
但是

好吧,又來但是了,App做完了之后,我們可愛的領(lǐng)導(dǎo)們感覺這個(gè)還可以,然后就又要開始發(fā)揮他們的各種NB的指導(dǎo)了,還好從一開始我們就沒有使用上班時(shí)間,這使得我們有理由拒絕領(lǐng)導(dǎo)的指導(dǎo),但是,公司卻說了,不接受指導(dǎo)那就不讓上,好吧,那就不上唄,這似乎惹怒了我們的領(lǐng)導(dǎo)們,所以,就直接沒有跟我們通氣的開始招兵買馬要上App了,我瞬間就想問:

  

我們的戰(zhàn)略不是說不做App么?現(xiàn)在怎么看到App比現(xiàn)在的簡(jiǎn)單就又開始做了

然后我又想到一種可能

我們把App上了,

另一個(gè)領(lǐng)導(dǎo)帶招一些新人把也做了一個(gè)App

如果App還可以的話,把我們的功能直接復(fù)制過去,然后讓我們的下線

然后領(lǐng)導(dǎo)又可以邀功了

如果App不可以的話,那我們是在浪費(fèi)時(shí)間,把我們的下線,然后……

反正,似乎都跟我沒半毛錢關(guān)系了,除非這個(gè)App運(yùn)營(yíng)的不好。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/64372.html

相關(guān)文章

  • 瀑布流—云南●十八怪

    摘要:瀑布流瀑布流式布局網(wǎng)站布局方式的一種視覺上表現(xiàn)為參差不齊的多欄布局。 瀑布流:瀑布流式布局(網(wǎng)站布局方式的一種)視覺上表現(xiàn)為參差不齊的多欄布局。應(yīng)用領(lǐng)域?yàn)椋弘娚虒?dǎo)購、興趣圖分享等頁面;其特點(diǎn)為琳瑯滿目、唯美、操作簡(jiǎn)單等特點(diǎn);布局優(yōu)點(diǎn)為有效的降低頁面復(fù)雜度、節(jié)省空間;交互方式更符合直覺;更高的參與度,以上兩點(diǎn)帶來的交互便捷性,可以使用戶側(cè)重于內(nèi)容而不是操作上。關(guān)于瀑布流的具體操作以云南●...

    cjie 評(píng)論0 收藏0
  • 忘了再看設(shè)計(jì)模式-結(jié)構(gòu)型

    摘要:推文設(shè)計(jì)模式適配器模式不兼容結(jié)構(gòu)的協(xié)調(diào)適配器模式四外觀模式老倉庫的角落,我們數(shù)著一麻袋的愛跟快樂初戀的顏色麥芽糖通過外觀角色來交互,降低子系統(tǒng)與客戶端的耦合度。 代理模式 我決定插手你的人生,當(dāng)你的時(shí)尚顧問 《陽光宅男》 通過代理對(duì)象進(jìn)行交互(或占位),強(qiáng)調(diào)訪問控制(也能增加額外功能,比如:日志);與被代理對(duì)象具有相同接口; showImg(https://segmentfault.c...

    URLOS 評(píng)論0 收藏0
  • 國(guó)慶怎么把主機(jī)帶回家-怎么把臺(tái)式電腦帶回家?

    摘要:怎么才能把臺(tái)式電腦帶回家可以寄嗎最好是自己帶著,麻煩點(diǎn)。如果非要寄就寄順豐,以下幾個(gè)建議供參考主機(jī)是否能找到原包裝,如果找到原包裝,里面的泡沫塑料是根據(jù)機(jī)型定制的,效果最好。怎么才能把臺(tái)式電腦帶回家?可以寄嗎?最好是自己帶著,麻煩點(diǎn)。如果非要寄就寄順豐,以下幾個(gè)建議供參考:主機(jī);1.是否能找到原包裝,如果找到原包裝,里面的泡沫塑料是根據(jù)機(jī)型定制的,效果最好。2.把機(jī)箱打開,顯卡拆下單獨(dú)打包,...

    Rango 評(píng)論0 收藏0
  • 關(guān)于js類型檢測(cè)

    摘要:原始類型又有種引用類型有而檢測(cè)這些類型的變量有種辦法,,。而關(guān)于引用類型,還可以嘗試下操作符。總而言之,如果指定則保存的實(shí)際上就是的值,是一個(gè)基本類型。 javascript的變量類型分為原始類型和引用類型。 原始類型又有5種: number string boolean null undefined 引用類型有: Function Array Date Object R...

    Cheriselalala 評(píng)論0 收藏0
  • Weex系列(4) —— 老生常談三端統(tǒng)

    摘要:剛看到這仨頁面的時(shí)候,我就想著可以用路由,做成三端統(tǒng)一。樣式這部分真的三端基本是高度統(tǒng)一的,部分微調(diào)一下就可以了,也正是這樣,我們后續(xù)才能迅速解決和。終于不是談?wù)勅私y(tǒng)一了,也是真的體驗(yàn)了一次,雖然最后有點(diǎn)出入,但是下次基本是沒問題了。 目錄 Weex系列(序) —— 總要知道原生的一點(diǎn)東東(iOS) Weex系列(序) —— 總要知道原生的一點(diǎn)東東(Android) Weex系列(...

    wzyplus 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<