用原生JS封装类jQuery的ajax方法

前言:为了深入理解jQuery中的ajax方法,本文通过使用原生JavaScript来封装一个类似的方法,能实现最基本的功能。其中会使用带promise方法。


1、ajax 的 基本功能

首先:
request = new XMLHttpRequest()

  • JS 可以设置任意请求 header :
    • 第一部分 request.open('get', '/xxx')
    • 第二部分 request.setRequestHeader('content-type','x-www-form-urlencoded')
    • 第四部分 request.send('a=1&b=2')
  • JS 可以获取任意响应 header 吗
    • 第一部分 response.status / request.statusText
    • 第二部分 response.getResponseHeader() / request.getAllResponseHeaders()
    • 第四部分 response.responseText

2、初始版本

封装:

window.jQuery.ajax = function(options){
  let method = options.method
  let url = options.url
  let headers = options.headers
  let body = options.body
  let failFn = options.failFn
  let successFn = options.successFn
  let request = new XMLHttpRequest()
  request.open(method,url)
  for(let key in headers){
    request.setRequestHeader(key,headers[key]) 
  }
  request.onreadystatechange = function(){
    if(request.readyState === 4){
      if(request.status >=200 && request.status < 400){
        successFn.call(undefined,request.responseText)
      }else{
        failFn.call(undefined,request.status)
      }
    } 
  }
  request.send(body)
}

调用:

  jQuery.ajax({
    url:'/xxx',
    method: 'post',
    headers:{'Content-Type':'application/x-www-form-urlencoded',enoch:18},
    body:'a=1&b=2',
    successFn:(e)=>{console.log(e)},
    failFn:(e)=>{console.log(e)}
  })

3、使用ES6新语法优化

  • 上面的代码中,好几行的let赋值看起来很傻,所以可以使用ES6的新语法:解构赋值来进行优化。
  • 首先简单的介绍一下ES6新语法之解构赋值MDN文档
    解构赋值语法是一个 Javascript 表达式,这使得可以将值从数组属性从对象提取到不同的变量中。举例说明:
// ES6 解构赋值示例
let a, b, rest;
[a, b] = [10, 20];
console.log(a); // 10
console.log(b); // 20

[a, b, ...rest] = [10, 20, 30, 40, 50];
console.log(a); // 10
console.log(b); // 20
console.log(rest); // [30, 40, 50]

({ a, b } = { a: 10, b: 20 });
console.log(a); // 10
console.log(b); // 20

// Stage 3 proposal
({a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40});
console.log(a); // 10
console.log(b); // 20
console.log(rest); //{c: 30, d: 40}

// 对象中的key值使用变量
var x = 'a' // 让obj中的x为'a'
var obj = {
   [x]:2
}
console.log(obj) // {a: 2}
  • 更改后的代码:
window.jQuery.ajax = function({method,url,headers,body,failFn,successFn}){
  let request = new XMLHttpRequest()
  request.open(method,url)
  for(let key in headers){
    request.setRequestHeader(key,headers[key]) 
  }
  request.onreadystatechange = function(){
    if(request.readyState === 4){
      if(request.status >=200 && request.status < 400){
        successFn.call(undefined,request.responseText)
      }else{
        failFn.call(undefined,request.status)
      }
    } 
  }
  request.send(body)
}

4、使用promise优化

  • 这里使用promise优化,主要解决的问题是:因为每个程序员的回调名不一样,你不看文档根本不知道这个库的函数名是什么,所以我们可以使用该方法不设置successFnfailFn这两个函数的函数名。

  • 优化后代码如下:
    封装:

window.jQuery.ajax = function({method,url,headers,body}){
  return new Promise(function(resolve,reject){
    let request = new XMLHttpRequest()
    request.open(method,url)
    for(let key in headers){
      request.setRequestHeader(key,headers[key])
    }
    request.onreadystatechange = function(){
      if(request.readyState === 4){
        if(request.status >=200 && request.status < 400){
          resolve.call(undefined,request.responseText)
        }else{
          reject.call(undefined,request.status)
        }
      }
    }
    request.send(body)
  })
}

调用:

  jQuery.ajax({
    url:'/xxx',
    method: 'post',
    headers:{'Content-Type':'application/x-www-form-urlencoded',enoch:18},
    body:'a=1&b=2',
  }).then(
    (e)=>{console.log(e)},
    (e)=>{console.log(e)}
  )

5、真正的jQuery的ajax方法

官方文档

jQuery.ajax()方法中,和我上面自己实现的有些许的名称差异:

  • successFn ==> success
  • failFn ==> error
  • headers中设置响应头的Content-Type属性 ==> dataType
  • data ==> body
  • jQuery也支持promise写法(成功第一个参数,失败第二个参数)
  • 等等

举例说明:

  • jQuery普通写法:
  jQuery.ajax({
    url:'/xxx',
    method: 'post',
    dataType:'x-www-form-urlencoded',
    data:'a=1&b=2',
    success:(e)=>{console.log(e)},
    error:(e)=>{console.log(e)}
  })
  • jQuery promise写法:
  jQuery.ajax({
    url:'/xxx',
    method: 'post',
    dataType:'json',
    data:'a=1&b=2',
  }).then(
    (e)=>{console.log(e)}, // 此时返回的是响应的responseText 的JSON.parse()的结果,即一个对象
    (e)=>{console.log('error')}
  )
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,402评论 6 499
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,377评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,483评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,165评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,176评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,146评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,032评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,896评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,311评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,536评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,696评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,413评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,008评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,815评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,698评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,592评论 2 353

推荐阅读更多精彩内容