账号密码登录
微信安全登录
微信扫描二维码登录

登录后绑定QQ、微信即可实现信息互通

手机验证码登录
找回密码返回
邮箱找回 手机找回
注册账号返回
其他登录方式
分享
  • 收藏
    X
    关于new Rx.Subject()和switchMap操作实现避免重复请求(或者说只保留一次请求)同时不影响其他请求?
    • 2017-10-22 00:00
    • 10
    37
    0

    在开发过程中,可能会遇到用户连续操作,而造成请求重复的问题(比如用户添加工作经验列表时WorkExperienceAdd可能重复添加),这个时候只需要一次请求即可,考虑到引入了rxjs想结合switchMap来实现,但是又不能影响到其他的请求(请求用户的工作经验列表WorkExperienceList),所以想请求一下帮助,有什么比较好的实现?

    1、websocket服务部分

    
    angular.module("app").factory("wsService", ["$q", "$ionicLoading", "i18n", "timeService", "commonService", "CONFIG",
      function ($q, $ionicLoading, i18n, timeService, commonService, CONFIG) {
        "use strict";
        const url = CONFIG.url.server;
        let ws = new WebSocket(url),
          arr = [],
          log = [],
          subject = new Rx.Subject();
          
        function reConnect(url) {
          let ws = new WebSocket(url);
          return bridgeWs(ws);
        }
    
        function send(data) {
          if (data) {
            sendData(data);
          } else {
            _.each(arr, item => {
              sendData(item);
            });
            arr = [];
          }
    
          function sendData(data) {
            if (data.parameters.showLoading) data.parameters = _.omit(data.parameters, ["showLoading"]);
            ws.send(JSON.stringify(data));
          }
        }
    
        function createRecord(msg, type) {
          const message = msg + " " + timeService.getTime() + " " + type.toUpperCase();
          log.push(message);
        }
    
    
        function message(event) {
          let data = JSON.parse(event.data);
          const criticalCode = 2000;
          data.isError = data.code > criticalCode;
          subject.next(data);
        }
    
        function close(event) {
          createRecord(event.reason, "close");
        }
    
        function error() {
          commonService.showShortCenter(i18n.server_error_tip);
          createRecord("connection error ", "error");
          console.error(log.join("\\n"));
        }
    
        function open() {
          !_.isEmpty(arr) && send();
          createRecord("connection established ", "open");
        }
    
      
        function bridgeWs(ws) {
          ws.onmessage = message;
          ws.onclose = close;
          ws.onerror = error;
          ws.onopen = open;
          return ws;
        }
    
        bridgeWs(ws);
    
        return {
          record: log,
    
          get: function (data) {
            console.log("get中的data");
            console.log(data);
            const readyState = 0,
              errorState = 2,
              closeState = 3;
            if (ws.readyState === readyState) {
              arr.push(data);
            } else if (_.includes([errorState, closeState], ws.readyState)) {
              ws.close();
              arr = [];
              arr.push(data);
              //TODO 重连直至连上为止
              ws = reConnect(url);
            } else {
              data.parameters.showLoading && commonService.showLoading();
              send(data);
              return new Date().getTime();
            }
          },
    
          close: ws.close,
    
          status: function () {
            return ws.readyState;
          },
    
          subject: subject
        };
      }]);
    

    2、api服务部分

    angular.module("app").factory("apiService", ["API", "i18n", "wsService", "$state", "commonService",
      function (API, i18n, wsService, $state, commonService) {
        "use strict";
    
        const subject = new Rx.Subject(),
          redirectCode = 2101;
    
        let parts = wsService.subject.partition(data => data.code === redirectCode);
    
        parts[0].subscribe(() => {
          $state.go("login");
        });
    
        parts[1].subscribe(data => {
          subject.next(data);
        });
    
      
        function createErrorSheet(item, record = {}) {
          if (_.isArray(item)) return _.map(item, commonService.curry2Right(_.assign)(record));
          return _.map(_.toPairs(item), ele => {
            let key = _.isArray(ele[1]) ? "key" : "form";
            record[key] = ele[0];
            return createErrorSheet(ele[1], record);
          });
        }
    
       
        function arrangeErrorInfo(data) {
          if (_.isString(data)) return data;
          return _.chain(data).map(item => createErrorSheet(item)).flattenDeep().value();
        }
    
        function curry2(fn) {
          return f => s => fn.call(fn, f, s);
        }
    
        class Command {
          constructor(path, parameters) {
            this.command = {path};
            this.parameters = parameters;
          }
        }
    
       
        const get = curry2((path, params) => {
          const option = new Command(path, params);
          console.log("get中的option");
          console.log(option);
          wsService.get(option);
        });
    
        class SubApi extends API {
          constructor() {
            super();
            this.subject = subject;
          }
    
          getLogin(param) {
            get(this.login)(param);
          }
          
         getWorkExperienceList(param) {
            get(this.workExperienceList)(param);
          }
          
         getWorkExperienceAdd(param) {
            get(this.workExperienceAdd)(param);
          }
          
          handleError(data) {
            commonService.hideLoading();
            const message = arrangeErrorInfo(data.detail),
              tip = _.isString(message) ? _.find([message, `1、${data.msg}`], _.identity) :
                _.map(message, (msg, index) => `${index + 1}、${msg.message}\n`).join("");
            try {
              window.plugins.toast.showLongCenter(tip);
            } catch (e) {
              commonService.alert(i18n.api_error_tip, tip);
            }
          }
    
         
          isDataOf(path, data) {
            return path === data.command.path;
          }
    
          
          isDataFor(data, ...path) {
            return _.includes(path, data.command.path);
          }
    
          predicatePath(path) {
            return data => path === data.command.path;
          }
        }
    
        return new SubApi();
      }]);

    3、页面逻辑(用户可以操作增加工作经验列表)

    angular.module("app").controller("personalCtrl", ["$scope", "apiService", "$state", "commonService", "ionicDatePicker",
      "$ionicPopover", "timeService", "$stateParams", "CONFIG", "$cordovaStatusbar", "validateService",
      function ($scope, apiService, $state, commonService, ionicDatePicker, $ionicPopover, timeService, $stateParams, CONFIG, $cordovaStatusbar, validateService) {
        "use strict";
    
        const i18n = $scope.i18n,
          current = $stateParams.subState;
        let isDateSelecting = false;
    
        function selectDate(ele) {
          if (isDateSelecting) return;
          const self = this; //don't fix, use automatic this;
          isDateSelecting = true;
          ionicDatePicker.openDatePicker({
            callback(val) {
              _.isString(ele) && (self.data[ele] = timeService.getDateInfo(val).fullDate);
              _.isObject(ele) && (ele.value = timeService.getDateInfo(val).fullDate);
              isDateSelecting = false;
            },
            cancel() {
              isDateSelecting = false;
            }
          });
        }
    
        const subject = new Rx.Subject(),
          apiServiceSubscription = apiService.subject.subscribe(data => {
            if (data.isError) {
              apiService.handleError(data);
            } else {
              subject.next(data);
            }
          });
        
        subject.filter(data => apiService.isDataOf(apiService.workExperienceList, data)).subscribe(() => {
          $scope[current].dealData(data.data);
        });
    
     subject.filter(data => apiService.isDataOf(apiService.workExperienceAdd, data)).subscribe(() => {
           $scope.editable = false;
          $scope.popover && $scope.popover.isShown() && $scope.popover.hide();
          $scope[current].queryData();
          $scope[current].clearCardInfo && $scope[current].clearCardInfo();
          $scope.$digest();
        });
    
    
     $scope.work = {
          title: "工作经验",
         
          platformData: {
            data: null,
            isShow: true
          },
          addData: {
            data: null,
            isShow: false
          },
         
          queryData() {
            const option = {
              sid: $scope.userInfo.sid,
              self: 1
            };
            apiService.getWorkExperienceList(option);  **// 查询工作经验**
          },
    
    
          addExperience() {
            const option = this.getOption();
            if (this.validateUserInput(option)) {
              apiService.getWorkExperienceAdd({       **// 增加工作经验**     
                sid: $scope.userInfo.sid,
                work_exper_form: option
              });
            }
          },
    
          validateUserInput() {
            return _.every(this.cardInfo, card => card.validateFn(card));
          },
       
          getOption() {
            return _.reduce(this.cardInfo, (accumlator, card) => {
              accumlator[card.key] = card.value;
              return accumlator;
            }, {});
          },
    
          init() {
            $state.go("home.personal.work");
            $scope.showAdd = true;
            this.queryData();
          }
        };
        
        $scope[current].init();
    
        $scope.$on("$ionicView.beforeLeave", () => {
          apiServiceSubscription.unsubscribe();
        });
      }]);
    
    1
    打赏
    收藏
    点击回答
    您的回答被采纳后将获得:提问者悬赏的 10 元积分
        全部回答
    • 共 0 条
    • 邝月 普通会员 1楼
      502 Bad Gateway

      502 Bad Gateway


      nginx
    更多回答
    扫一扫访问手机版
    • 回到顶部
    • 回到顶部