zoukankan      html  css  js  c++  java
  • zepto源码研究

    简要:ajax请求具有能够触发各类事件的功能,包括:触发全局事件,请求发送前事件,请求开始事件,请求结束事件等等,贯穿整个ajax请求过程,这是非常有用的,我们可以利用这些事件来做一些非常有意思的事情比如:拦截器,权限管理等等,另外$.ajax()貌似会返回一个异步请求对象xhr,这个xhr也是继承了defer的promise对象。这些事件中全局事件是绑定在document上的,局部事件由settings.content指定。(不管怎么说事件都是绑定在dom元素上的,至于事件为什么要与dom关联,可能是为了重用event.js吧,本人在此挖个坑,若有人知道,希望能指点一二)。

    闲话少说,直接上代码:

    /**
       *
       * 触发自定义事件
       * @param context
       * @param eventName
       * @param data
       * @returns {boolean}
       */
      function triggerAndReturn(context, eventName, data) {
        var event = $.Event(eventName)   //创建Event对象
        $(context).trigger(event, data)   //触发,这里event参数也可以为字符串,但这里对eventName的校验放到$.Event里面区实现
        return !event.isDefaultPrevented()   //TODO:返回event.isDefaultPrevented?
      }
    
      // trigger an Ajax "global" event
    
      /**
       * 触发ajax的全局事件
       * @param settings
       * @param context
       * @param eventName
       * @param data
       * @returns {*}
       */
      function triggerGlobal(settings, context, eventName, data) {
        //settings.global   是否触发ajax的全局事件
        if (settings.global) return triggerAndReturn(context || document, eventName, data);
      }

    triggerGlobal是一个公用函数,在ajaxStart,ajaxStop,ajaxBeforeSend,,ajaxSend,ajaxSuccess,ajaxError,ajaxComplete这些方法中触发全局事件,

    除了ajaxStart,和ajaxStop 触发绑定在document上的对应事件外,其他的会触发settings.content绑定的事件。

    如果你在settings里不设置global为true,则ajax是不会触发各类事件的。

    $.active = 0
    
    
      /**
       * 触发全局 ‘ajaxStart’事件
       * @param settings
       */
      function ajaxStart(settings) {
        //settings.global 传递进来的是否触发全局事件参数
        //$.active++ === 0      $.active = 0,此判断才会true
        if (settings.global && $.active++ === 0) triggerGlobal(settings, null, 'ajaxStart')
      }
      /**
       * 尝试抛出所有请求停止事件,写法和ajaxStart相同
       * @param settings
       */
      function ajaxStop(settings) {
        if (settings.global && !(--$.active)) triggerGlobal(settings, null, 'ajaxStop')
      }

    ajaxStart:如果允许触发全局事件(settings.global),且当前事件为$内部第一个ajax请求,则执行document所绑定的ajaxStart事件。

    $.active++ === 0会先若$.active与0比较,然后自加。

    // triggers an extra global event "ajaxBeforeSend" that's like "ajaxSend" but cancelable
      //触发全局ajaxBeforeSend事件,如果返回false,则取消此次请求
    
      /**
       * 请求前置器, beforeSend ,返回false,取消此次请求
       * 或抛出 ajaxBeforeSend 全局事件
       * 抛出ajaxSend事件
       *
       * @param xhr
       * @param settings
       * @returns {boolean}
       */
      function ajaxBeforeSend(xhr, settings) {
        var context = settings.context
        if (settings.beforeSend.call(context, xhr, settings) === false ||
            triggerGlobal(settings, context, 'ajaxBeforeSend', [xhr, settings]) === false)
          return false
    
        triggerGlobal(settings, context, 'ajaxSend', [xhr, settings])
      }

    ajaxBeforeSend:   可用于拦截请求,判断并决定请求是否发送。这里定义了2个位置可以处理请求,1:settings.beforeSend 函数,2:settings.context所绑定的

    ajaxBeforeSend事件。只要其中有一个function返回false,则终止请求。

    /**
       * 请求成功调用函数
       * @param data
       * @param xhr
       * @param settings
       * @param deferred
       */
      function ajaxSuccess(data, xhr, settings, deferred) {
        var context = settings.context, status = 'success'
    
        //调用success函数
        settings.success.call(context, data, status, xhr)
    
        //调用所有成功回调函数
        if (deferred) deferred.resolveWith(context, [data, status, xhr])
    
        //抛出全局事件  'ajaxSuccess'
        triggerGlobal(settings, context, 'ajaxSuccess', [xhr, settings, data])
    
    
        //请求完成
        ajaxComplete(status, xhr, settings)
      }
      // type: "timeout", "error", "abort", "parsererror"
      /**
       * 请求失败调用函数
       * @param error
       * @param type
       * @param xhr
       * @param settings
       * @param deferred
       */
      function ajaxError(error, type, xhr, settings, deferred) {
        var context = settings.context
        settings.error.call(context, xhr, type, error)
        if (deferred) deferred.rejectWith(context, [xhr, type, error])
        triggerGlobal(settings, context, 'ajaxError', [xhr, settings, error || type])
        ajaxComplete(type, xhr, settings);
      }
      // status: "success", "notmodified", "error", "timeout", "abort", "parsererror"
      /**
       * 请求完成调用函数
       * @param status
       * @param xhr
       * @param settings
       */
      function ajaxComplete(status, xhr, settings) {
        var context = settings.context
    
        //执行complete
        settings.complete.call(context, xhr, status)
        triggerGlobal(settings, context, 'ajaxComplete', [xhr, settings])
    
        //尝试抛出所有请求停止事件
        ajaxStop(settings)
      }

    $.ajax({url:'http://192.168.1.189:8080/api/v1/_products/get',data:{name:'zhutao'},method:'POST'})
    .then(function(){console.log(arguments);}); Object {} [Object, "success", Object]
    $.ajax({url:
    'http://192.168.1.189:8080/api/v1/_products/get',data:{name:'zhutao'},method:'POST'})
    .then(function(){console.log('SUCCESS',arguments);}); Object {} SUCCESS [Object, "success", Object]0: Objectcode: 9998entity: nullmessage: "商品不存在"__proto__: Object__defineGetter__: __defineGetter__()__defineSetter__: __defineSetter__()__lookupGetter__: __lookupGetter__()__lookupSetter__: __lookupSetter__()constructor: Object()hasOwnProperty: hasOwnProperty()isPrototypeOf: isPrototypeOf()propertyIsEnumerable: propertyIsEnumerable()toLocaleString: toLocaleString()toString: toString()valueOf: valueOf()get __proto__: get __proto__()set __proto__: set __proto__()1: "success"2: Objectabort: (e)always: ()complete: ()done: ()error: ()fail: ()getAllResponseHeaders: ()getResponseHeader: (e)overrideMimeType: (e)pipe: ()progress: ()arguments: nullcaller: nulllength: 0name: ""prototype: Object__proto__: ()<function scope>promise: (e)arguments: nullcaller: nulllength: 1name: ""prototype: Object__proto__: ()<function scope>readyState: 4responseJSON: ObjectresponseText: "{"code":9998,"message":"商品不存在","entity":null}"setRequestHeader: (e,t)arguments: nullcaller: nulllength: 2name: ""prototype: Object__proto__: ()<function scope>state: ()status: 200statusCode: (e)statusText: "OK"success: ()then: ()__proto__: Objectcallee: ()arguments: nullcaller: nulllength: 0name: ""prototype: Object__proto__: ()<function scope>length: 3Symbol(Symbol.iterator): values()__proto__: Object
    $.ajax({url:
    '/get',data:{name:'zhutao'}}).then(function(){console.log('SUCCESS',arguments);},function(){console.log('error');}); Object {} GET http://192.168.1.198:8000/get?name=zhutao 404 (Not Found) error

    执行ajax的回调函数有两种,1:$.ajax({.....,success:function(){}});   2:$.ajax({...}).then(function(){});   

    settings.success  会先执行,然后执行deffer.resolve();利用$.ajax()返回的promise,我们能很方便的做很多事情。

  • 相关阅读:
    .NET 4.0 中的契约式编程
    DELL安装Windows Server 2019
    Mysql 5.7.34免安装版本
    MQTT
    WPF属性
    WPF数据绑定
    git系列之(五)git stash 命令
    Vue.js
    git 对比两个分支差异
    TPL 之二 TransformBlock
  • 原文地址:https://www.cnblogs.com/zhutao/p/5824594.html
Copyright © 2011-2022 走看看