打包app 华为手机ajax失败引发的---重写jQuery的ajax方法

本文为18.11.8重新编写,原题目:extend合并对象

经测试,在华为Mate 10 的 EMUI 8.1 版本 8.1.0.336 下进行ajax调用出现异常(其他安卓手机调用正常);在调用后ajax会默认进入success并返回空数据。

所以首先尝试用原生的请求数据(配用appcan的插件),发现可以获取到数据~涉及到项目代码的改动。

那么为了解决这个问题:只好 重写ajax!!!!

一、前提知识(系统温习一下)

1. (function($){….})(jQuery)

第一个括号里边的function($){….}实际上就是一个匿名函数,它的形参是$,其实这里主要是为了不与其它的库冲突。

我们在调用函数的时候,通常都是函数名后边加上括号以及实参,但是由于操作符的优先级我们定义的匿名函数也需要用()括起来,所以就有了前面的(function($){....})。

第一个括号表示定义了一个匿名函数,然后(jQuery)表示为该函数传递的参数,整个结合起来意思就是,定义了一个匿名函数,然后又调用该函数,并传递实参jQuery,相当于——function fun($){…};fun(jQuery);

       这种方法多用于存放开发的插件,执行其中的代码时,Dom对象并不一定加载完毕。于此相反的是$(function(){}),这种方法在使用时页面的Dom对象已经加载完毕了。事实上该方法的全写是:$(document).ready(function(){});
---------------------

2.$.fn.extend和$.extend

jQuery.fn.extend(object);//为jQuery的实例对象添加方法

jQuery.extend(object);//为jQuery类本身扩展,添加新的方法或覆盖原有的方法

$.fn.extend表示的是为原型对象扩展方法,使用此方式扩展的方法只能用对象去调用,example:

$.fn.extend({
    test:function(){
        alert("test");
    }
});
$("#id").test();

$.extend就可以直接用$在其他地方来调用此扩展方法了,example:

$.extend({
    test:function(param){
        alert(param);
    }
});
$.test(1);//则直接弹出1
2.1 extend(result,item1,item2…..)

这里这个方法主要用来合并,将所有的参数项都合并result中,并返回result,但是这样就会破坏result的结构。

2.2 extend({},item1,item2,……)

用这个方法,可以将所得的结果全部合并在{}中,并返回,而且还不会破坏原有的项的结构。

示例:

Var item={name:”olive”,age:23};

Var item1={name:”Momo”,sex:”gril”};

Var result=$.extend({},item,item1);

结果:

Result={name:”Momo”,age:23,sex:”gril”};

2.3 extend(bool,{},item1,item2….)

Extend方法还有带bool型参数的重载。

bool型参数为true表示深拷贝,为false时表示浅拷贝。具体可以通过一下示例来说明:

示例:

var item={name:“olive”,age:23,address{provice:”河南”,city:”郑州”}};
var item1={sex:”girl”,address{city:”北京”}};
var result=$.extend(true,item,item1);
var result1=$.extend(false,item,item1);

结果:
Result={name:“olive”,age:23,sex:”gril”,address:{provice:”河南”,city:”北京”}};
Result1={name:“olive”,age:23,sex:”gril”,address:{ city:”北京”}};

说明:

以上结果说明,当参数为ture时,即为深拷贝,当子项item1中的子项有与item中的子项相同属性的值不一样时,item1中子项的值会将item子项中的值给覆盖,当子项item1的属性跟item中的属性不同时,会与item进行合并。

当参数为false时,子项item1中的子项中与item中的子项属性相同时,item1中子项的属性值会将item中的值给完全覆盖。

重点 :重写方法 用的是原生方式自己处理的,没有采用网上一搜一大把的完全一样的文章!

方式1:
$.extend($.ajax,{ ajax:
function (opt) { .......this.options =$.extend({},this.defaults,opt); .......... } })

方式2:()
$.ajax = function (opt) {
this.defaults ={
'type': 'post',
'url': '',
'data':'',
'timeout':30000,
'async':true,
'contentType': "application/json",
'success':function () {},
'error':function () {}
}
//this.options =$.extend({},this.defaults,opt);//A
var thisoptions =$.extend({},this.defaults,opt);
console.log(this.options)
var self = this;
var xhr = new XMLHttpRequest();
xhr.open(thisoptions.type,thisoptions.url,thisoptions.async);
xhr.setRequestHeader('Content-Type',thisoptions.contentType);
xhr.send(thisoptions.data); //发送
xhr.onreadystatechange = function(event){
if(xhr.readyState == 4){
if (xhr.status >= 200 && xhr.status < 300) {
var message = '';
try {
message = JSON.parse(xhr.responseText);
} catch (err) {
self.options.error(err.message, xhr.status, xhr,2);
}
if (message) {
thisoptions.success(message, xhr.status, xhr,3);
}
} else {
self.options.error(xhr.statusText, xhr.status, xhr,4);
}
}
}
if(thisoptions.timeout > 0){
xhr.ontimeout = function () {
self.options.error(xhr.statusText, xhr.status, xhr);
};
}
}
 

至此:就可以使用了!

发现的问题:

1.请求头的问题。这个封装方式 需要单独的设置请求头!由于项目中 存在多个服务,而且这些服务是不的人不同的时间段写的。一个请求头高端华为手机竟然没法同时满足,

2.发现的bug:$.extend({})问题

这里最初仅仅是$.extend({})形式。项目中竟然出现了请求2次数据的问题!也就是说:重写的ajax没有覆盖 jQuery的,依然会执行jQuery的ajax!

然后升级一下:$.extend(true,$.ajax,{}),本以为这样会覆盖jQuery了。第二天发现还是不行!------------由于多个项目中都用了$.ajax形式,那么想到过 把jQuery的ajax换个名字,换个名字是做到清除jQuery的ajax的影响了~~但是改了jQuery,不合时宜!!

最终:直接 $.ajax = function(){}方式!

3.重大问题:

方式1 中的 this.options =$.extend({},this.defaults,opt) 到了方式2 中,变了~~~ 就这么一句代码 给我造成了大困扰!尝试了一天多的解决方式!

方式一中的 写法,有个有趣的现象:如果是同时执行多个ajax函数!每个都会返回正常值,但是:返回的正常值会按最后一个函数的回调方式 处理!!!

//三个ajax函数
fun1()
fun2()
fun3()
//三个都会返回自己的值。但是 都会按照fun3的处理方式处理返回值!!!
//单独一个函数还好

//想过 依次调用回调 执行,但这样依旧没有从根本上解决问题!!!其实还是封装写法某个地方出的问题---- this.options =$.extend({},this.defaults,opt) 引起的

 

扩展:原生JavaScript实现ajax

function ajax(options) {
    options = options || {};
    options.type = (options.type || "GET").toUpperCase();
    options.dataType = options.dataType || "json";
    var params = (options.data);
    //创建xhr对象 - 非IE6
    if (window.XMLHttpRequest) {
        var xhr = new XMLHttpRequest();
    } else { //IE6及其以下版本浏览器
        var xhr = new ActiveXObject('Microsoft.XMLHTTP');
    }
    //GET POST 两种请求方式
    if (options.type == "GET") {
        xhr.open("GET", options.url + "?" + params, true);
        xhr.send(null);
    } else if (options.type == "POST") {
        xhr.open("POST", options.url, true);
        //设置表单提交时的内容类型
        xhr.setRequestHeader("Content-Type", "application/json");
        xhr.send(params);
    }
    //接收
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4) {
            var status = xhr.status;
            if (status >= 200 && status < 300) {
                options.success && options.success(JSON.parse(xhr.responseText));
            } else {
                options.fail && options.fail(status);
            }
        }
    }
}

扩展:zepto.js的ajax实现

appcan封装的ajax完全就是zepto.js

zepto.js 源码带注释 说明连接 http://www.runoob.com/w3cnote/zepto-js-source-analysis.html

扩展:原生JavaScript实现extend

var obj1 = {'a': 'obj2','b':'2'};
var obj2 = {name: 'obj3'};
function extend() {
    var length = arguments.length;
    var target = arguments[0] || {};
    if (typeof target!="object" && typeof target != "function") {
        target = {};
    }
    if (length == 1) {
        target = this;
        i--;
    }
    for (var i = 1; i < length; i++) { 
        var source = arguments[i]; 
        for (var key in source) { 
            // 使用for in会遍历数组所有的可枚举属性,包括原型。
            if (Object.prototype.hasOwnProperty.call(source, key)) { 
                target[key] = source[key]; 
            } 
        } 
    }
    return target; 
}
console.log(extend(obj1,obj2));

 

 

原文内容:

需求:设有对象 o1 ,o2,需要得到对象 o3  

方法1:使用JQuery的extend方法

 **方法定义**:jQuery.extend([deep], target, object1, [objectN])

    > 用一个或多个其他对象来扩展一个对象,返回被扩展的对象。

 > 如果不指定target,则给jQuery命名空间本身进行扩展。这有助于插件作者为jQuery增加新方法。 如果第一个参数设置为true,则jQuery返回一个深层次的副本,递归地复制找到的任何对象(递归合并)。否则的话,副本会与原对象共享结构。 未定义的属性将不会被复制,然而从对象的原型继承的属性将会被复制。

o3 = $.extend(o1, o2)  // 合并 o1 和 o2, 将结果返回给 o3. 注意: 此时,o1 == o3! 即 o1 被修改
//
o3 = $.extend({}, o1, o2) // 合并 o1 和 o2, 将结果返回给 o3. 注意: 此时,o1 != o3! 即 o1 没有被修改

方法2:用 Object.assign();

var o1 = { a: 1 };
var o2 = { b: 2 };
var o3 = { c: 3 };
 
var obj = Object.assign(o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
console.log(o1);  // { a: 1, b: 2, c: 3 }, 注意目标对象自身也会改变。  

JavaScript中Math.abs()方法的使用

Math.abs( x ) ;

  • 返回一个数字的绝对值

 

 

 

333

转载于:https://www.cnblogs.com/lovelgx/articles/7424378.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值