Contents
  1. 1. 什么是ajax
  2. 2. ajax的语法(http头)
  3. 3. jquery的语法(根据接受类型用json.parse等)
  4. 4. jsonp
  5. 5. promise的语法
    1. 5.1. Promise标准解读
  6. 6. promise的原理
  7. 7. fetch的api

什么是ajax

AJAX即“Asynchronous JavaScript and XML”(异步的JavaScript与XML技术),指的是一套综合了多项技术的浏览器端网页开发技术。

据我了解ajax概念很久之前就有了,但真正流行起来是因为谷歌的应用。

ajax的语法(http头)

1
2
3
4
5
if (window.XMLHttpRequest) { // Mozilla, Safari, ...
http_request = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
http_request = new ActiveXObject("Microsoft.XMLHTTP");
}

上面创建了一个http的对象,为了兼容ie的浏览器。
如果服务器的响应没有XML mime-type header,某些Mozilla浏览器可能无法正常工作. 为了解决这个问题, 如果服务器响应的header不是text/xml,可以调用其它方法修改该header

1
2
http_request = new XMLHttpRequest();
http_request.overrideMimeType('text/xml');

然后在不同的状态嘬出不通过的响应。
http_request.onreadystatechange = function(){
// do the thing
};
然后就可以调用open()和send()

1
2
http_request.open('GET','http://www.example.org/some.file', true);
http_request.send(null);
  • open()的第一个参数是HTTP请求方式 – GET, POST, HEAD 或任何服务器所支持的您想调用的方式. 按照HTTP规范,该参数要大写;否则,某些浏览器(如Firefox)可能无法处理请求.有关HTTP请求方法的详细信息可参考http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html W3C specs
  • 第二个参数是请求页面的URL.由于自身安全特性的限制,该页面不能为第三方域名的页面.同时一定要保证在所有的页面中都使用准确的域名,否则调用open()会得到”permission denied”的错误提示.一个常见的错误是访问站点时使用domain.tld,而当请求页面时,却使用www.domain.tld.
  • 第三个参数设置请求是否为异步模式.如果是TRUE, JavaScript函数将继续执行,而不等待服务器响应.这就是”AJAX”中的”A”.

如果第一个参数是POST,就可以根据mime头来传递字符串

1
2
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send("fname=Bill&lname=Gates");

然后就是根据readyState来做出判断

1
2
3
4
5
if (http_request.readyState == 4) {
// everything is good, the response is received
} else {
// still not ready
}

readyState的取值如下:

  • 0 (未初始化) UNSENT
  • 1 (正在装载) OPENED
  • 2 (装载完毕) HEADERS_RECEIVED
  • 3 (交互中) LOADING
  • 4 (完成) DONE

接着,函数会检查HTTP服务器响应的状态值. 完整的状态取值可参见 W3C site. 我们着重看值为200 OK的响应.

1
2
3
4
5
6
7
if (http_request.status == 200) {
// perfect!
} else {
// there was a problem with the request,
// for example the response may be a 404 (Not Found)
// or 500 (Internal Server Error) response codes
}

jquery的语法(根据接受类型用json.parse等)

1
jQuery.ajax(url,[settings])
  • beforeSend 在发送请求之前调用,并且传入一个XMLHttpRequest作为参数。
  • error 在请求出错时调用。传入XMLHttpRequest对象,描述错误类型的字符串以及一个异常对象(如果有的话)
  • dataFilter 在请求成功之后调用。传入返回的数据以及”dataType”参数的值。并且必须返回新的数据(可能是处理过的)传递给success回调函数。
  • success 当请求之后调用。传入返回后的数据,以及包含成功代码的字符串。

tips:
这里jquery会判断服务器传回来的mime头如果是json,就会自动把data转换为对象。

  • complete 当请求完成之后调用这个函数,无论成功或失败。传入XMLHttpRequest对象,以及一个包含成功或错误代码的字符串。

具体api

jsonp

ajax为了安全不能跨域,为了解决这个问题,部的不佩服开发者的脑子想出——jsonp方法,当然也有别的解决方法。
下面以一个事例介绍一下jsonp

服务器端代码:

1
2
3
4
5
6
7
8
9
10
11
const http=require('http');
http.createServer(function(req,res){
res.writeHead(200,{
'Content-Type':'text/plain'
});
if(req.url.indexOf('?')!=-1)
{
var callback=req.url.slice(req.url.indexOf('=')+1,req.url.length)
res.end(callback+'("Hello world")');
}
}).listen(1337);

客户端JS

1
2
3
4
5
6
7
8
9
10
11
function newScript(src){
var script=document.createElement('script');
document.body.appendChild(script);
script.src=src;
return script;
}
var test=function(str) {
// body...
console.log(str)
}
newScript('http://localhost:1337/?callback=test')

这样就形成跨域,具体链接

promise的语法

本来直接看fetch的语法,然后看到fetch可以看成promise的语法下的ajax。
然后我就好奇什么是promise?

  • 参考链接阮一峰es6promise

    Promise标准解读

  • 只有一个then方法,没有catch,race,all等方法,甚至没有构造函数

    Promise标准中仅指定了Promise对象的then方法的行为,其它一切我们常见的方法/函数都并没有指定,包括catch,race,all等常用方法,甚至也没有指定该如何构造出一个Promise对象,另外then也没有一般实现中(Q, $q等)所支持的第三个参数,一般称onProgress

  • then方法返回一个新的Promise

Promise的then方法返回一个新的Promise,而不是返回this,此处在下文会有更多解释

1
2
promise2 = promise1.then(alert)
promise2 != promise1 // true

  • 不同Promise的实现需要可以相互调用(interoperable)

  • Promise的初始状态为pending,它可以由此状态转换为fulfilled(本文为了一致把此状态叫做resolved)或者rejected,一旦状态确定,就不可以再次转换为其它状态,状态确定的过程称为settle

更具体的标准见这里
这是我写的promise版的ajax

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function promiseAjax(url){
return new Promise(function(resolve,reject){
if (window.XMLHttpRequest) { // Mozilla, Safari, ...
http_request = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
http_request = new ActiveXObject("Microsoft.XMLHTTP");
}
http_request.open('GET',url, true);
http_request.send(null);
http_request.onload=function(){
if(this.status==200){
resolve(this.responseText);
}else {
reject(new Error(this.statusText));
}
}
http_request.onerror=function(){
};
})
}
promiseAjax('http://localhost:1337').then(function(res){
console.log(res)
},function(err){
console.log(err)
})

服务器端用node:

1
2
3
4
5
6
7
8
9
10
11
12
const http=require('http');
http.createServer(function(req,res){
if (req.url == '/favicon.ico')
return;
//res.setHeader('Access-Control-Allow-Origin','*');
res.writeHead(200,{
'Content-Type':'text/plain',
'Access-Control-Allow-Origin':'*'
});
res.end("Hello world");
}).listen(1337);

promise的原理

看了一步一步实现promise的代码,相关链接
看完本来我会回调函数的,看完彻底懵逼了,本来没有用过promise然后用了一天,看了阮一峰的promise教程,然后把实现原理看来一遍,然后整整想了两天,才大概想明白,
其实这正真反应出对现实的抽象能力。也正是我想做的。
因为介绍也很具体了,我这里就不班门弄斧了。
只要注意promise的应用情形。不能应用在频繁更改状态的情形。

fetch的api

fetch说简单点就是一个promise版的ajax但是听了贺老师说的如果真的是一个简单的语法糖,是不会加到新的标准里的,肯定有别的应用。
首先我们来看看fetch的兼容度,当然可以自己写兼容,基本上新浏览器都支持ie是完全不支持的。
use:

1
Promise<Response> fetch(input[, init]);

返回一个response对象。
fetch(url).then(respone):

1
2
3
4
5
6
7
8
9
10
var myImage = document.querySelector('img');
fetch('flowers.jpg')
.then(function(response) {
return response.blob();
})
.then(function(myBlob) {
var objectURL = URL.createObjectURL(myBlob);
myImage.src = objectURL;
});

Here we are fetching an image across the network and inserting it into an element. The simplest use of fetch() takes one argument — the path to the resource you want to fetch — and returns a promise containing the response (a Response object).

This is just an HTTP response of course, not the actual image. To extract the image body content from the response, we use the blob() method (defined on the Body mixin, which is implemented by both the Request and Response objects.)

TODO:URL.createObjectURL

提供请求选项

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var myHeaders = new Headers();
var myInit = { method: 'GET',
headers: myHeaders,
mode: 'cors',
cache: 'default' };
fetch('flowers.jpg',myInit)
.then(function(response) {
return response.blob();
})
.then(function(myBlob) {
var objectURL = URL.createObjectURL(myBlob);
myImage.src = objectURL;
});

选项内容

  • method: The request method, e.g., GET, POST.
  • headers: Any headers you want to add to your request, contained within a Headers object or an object literal with ByteString values.
  • body: Any body that you want to add to your request: this can be a Blob, BufferSource, FormData, URLSearchParams, or USVString object. Note that a request using the GET or HEAD method cannot have a body.
  • mode: The mode you want to use for the request, e.g., cors, no-cors, or same-origin.
  • credentials: The request credentials you want to use for the request: omit, same-origin, or include. To automatically send cookies for the current domain, this option must be provided. Starting with Chrome 50, this property also takes a FederatedCredential instance or a PasswordCredential instance.
  • cache: The cache mode you want to use for the request: default, no-store, reload, no-cache, force-cache, or only-if-cached.
  • redirect: The redirect mode to use: follow (automatically follow redirects), error (abort with an error if a redirect occurs), or manual (handle redirects manually). In Chrome the default was follow before Chrome 47 and manual starting with Chrome 47.
  • referrer: A USVString specifying no-referrer, client, or a URL. The default is client.
  • referrerPolicy: Specifies the value of the referer HTTP header. May be one of no-referrer, no-referrer-when-downgrade, origin, origin-when-cross-origin, unsafe-url.
  • integrity: Contains the subresource integrity value of the request (e.g., sha256-BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE=).

确定相应成功:

1
2
3
4
5
6
7
8
9
10
11
12
13
fetch('flowers.jpg').then(function(response) {
if(response.ok) {
response.blob().then(function(myBlob) {
var objectURL = URL.createObjectURL(myBlob);
myImage.src = objectURL;
});
} else {
console.log('Network response was not ok.');
}
})
.catch(function(error) {
console.log('There has been a problem with your fetch operation: ' + error.message);
});

注意catch抓却到的错误是代码运行出错。

request:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var myHeaders = new Headers();
var myInit = { method: 'GET',
headers: myHeaders,
mode: 'cors',
cache: 'default' };
var myRequest = new Request('flowers.jpg', myInit);
fetch(myRequest, myInit)
.then(function(response) {
return response.blob();
})
.then(function(myBlob) {
var objectURL = URL.createObjectURL(myBlob);
myImage.src = objectURL;

request接受fetch一样的参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var myHeaders = new Headers();
var myInit = { method: 'GET',
headers: myHeaders,
mode: 'cors',
cache: 'default' };
var myRequest = new Request('flowers.jpg', myInit);
fetch(myRequest, myInit)
.then(function(response) {
return response.blob();
})
.then(function(myBlob) {
var objectURL = URL.createObjectURL(myBlob);
myImage.src = objectURL;
});

Header对象

var myHeaders = new Headers(init);

有get 和append等方法。

1
2
myHeaders.append('Content-Type', 'image/jpeg');
myHeaders.get('Content-Type'); // Returns 'image/jpeg'

Response对象:
注意有一下几种转换方法:

-arrayBuffer()

-blob()

-json()

-text()

-formData()

Contents
  1. 1. 什么是ajax
  2. 2. ajax的语法(http头)
  3. 3. jquery的语法(根据接受类型用json.parse等)
  4. 4. jsonp
  5. 5. promise的语法
    1. 5.1. Promise标准解读
  6. 6. promise的原理
  7. 7. fetch的api