来台湾出差快一个星期了,相比大陆深圳,还是更喜欢内地多点,这边的天气实在不敢恭维,天天下雨,交通汽车尾气太重了,摩托车四处穿插.....休息时间还是呆在家里,写写东西,给大家分享点干货,今天来聊点数据ajax的基础知识。
2019年3月庆祝Ajax成立20周年。有点。XMLHttpRequest
作为IE5.0 ActiveX组件于1999年交付的第一个实现(不要问)。
在此之前,曾经有一些方法可以在不刷新整个页面的情况下从服务器提取数据,但是它们通常依赖于笨拙的技术,例如<script>
注入或第三方插件。Microsoft XMLHttpRequest
为Outlook电子邮件客户端开发了一种基于浏览器的替代产品。
XMLHttpRequest
直到2006年才成为Web标准,但大多数浏览器都实现了该标准。它在Gmail(2004)和Google Maps(2005)中的采用导致Jesse James Garrett在2005年发表的文章AJAX:一种新的Web应用程序方法。新术语明确了开发人员的重点。
AJAX to Ajax
AJAX是异步JavaScript和XML的助记符。绝对是"异步的",但是:
可以使用JavaScript,尽管可以选择VBScript和Flash
有效负载不必是XML,尽管在当时很流行。可以使用任何数据格式,今天,通常首选JSON。
现在,我们将" Ajax"用作任何客户端过程的通用术语,该过程从服务器获取数据并动态更新DOM,而无需刷新整个页面。Ajax是大多数Web应用程序和单页应用程序(SPA)的核心技术。
极端XMLHttpRequest
以下JavaScript代码示出了用于一个基本HTTP GET请求http://domain/service
使用XMLHttpRequest
(通常缩写为XHR):
let xhr = new XMLHttpRequest();xhr.open('GET', 'http://domain/service');// request state change eventxhr.onreadystatechange = function() {
// request completed?
if (xhr.readyState !== 4) return;
if (xhr.status === 200) {
// request successful - show response
console.log(xhr.responseText);
}
else {
// request error
console.log('HTTP error', xhr.status, xhr.statusText);
}};// start requestxhr.send();
该XMLHttpRequest
对象具有许多其他选项,事件和响应属性。例如,可以设置和检测以毫秒为单位的超时:
// set timeout
xhr.timeout = 3000; // 3 seconds
xhr.ontimeout = () => console.log('timeout', xhr.responseURL);
一个progress
事件可以报告长时间运行的文件上传:
// upload progress
xhr.upload.onprogress = p => {
console.log( Math.round((p.loaded / p.total) * 100) + '%') ;
}
选项的数量可能令人困惑,并且早期实现XMLHttpRequest
存在一些跨浏览器不一致的情况。因此,大多数库和框架都提供Ajax包装函数来处理复杂性,例如jQuery.ajax()
方法:
// jQuery Ajax
$.ajax('http://domain/service')
.done(data => console.log(data))
.fail((xhr, status) => console.log('error:', status));
Fast Forward to Fetch
该提取API是一个现代化的替代品XMLHttpRequest
。通用的Headers,Request和Response接口提供了一致性,而Promises允许更容易的链接和异步/等待而没有回调。上面的XHR示例可以转换为更简单的基于Fetch的代码,甚至可以解析返回的JSON:
fetch(
'http://domain/service',
{ method: 'GET' }
)
.then( response => response.json() )
.then( json => console.log(json) )
.catch( error => console.error('error:', error) );
Fetch干净,优雅,易于理解,并且在PWA Service Worker中大量使用。为什么不使用它代替古老的XMLHttpRequest?
不幸的是,Web开发从未如此明确。Fetch尚未完全替代Ajax技术...
浏览器支持 {#browsersupport}
Fetch API得到了很好的支持,但是在所有版本的Internet Explorer中都将失败。使用2017年之前版本的Chrome,Firefox和Safari的人可能也会遇到问题。这些用户可能只占您用户群的一小部分......或者可能是主要客户。开始编码之前,请务必检查!
此外,与成熟的XHR对象相比,Fetch API较新,并且可以接收更多正在进行的更改。这些更新不太可能破坏代码,但是希望在未来几年中进行一些维护工作。
默认无Cookie {#cookielessbydefault}
与不同XMLHttpRequest
,并非所有Fetch的实现都会发送Cookie,因此您的应用程序的身份验证可能会失败。可以通过更改第二个参数中传递的启动选项来解决此问题,例如
fetch(
'http://domain/service',
{
method: 'GET',
credentials: 'same-origin'
}
)
错误不会被拒绝 {#errorsarenotrejected}
令人惊讶的是,HTTP错误(例如404 Page Not Found
或)500 Internal Server Error
不会导致Fetch Promise拒绝;将.catch()
永远不会运行。通常,它将response.ok
状态设置为false进行解析。
仅当请求无法完成(例如,网络故障)时才发生拒绝。这会使错误捕获的实现更加复杂。
不支持超时 {#timeoutsarenotsupported}
提取不支持超时,只要浏览器选择,请求将继续。需要进一步的代码将Fetch包装在另一个Promise中,例如
// fetch with a timeoutfunction fetchTimeout(url, init, timeout = 3000) {
return new Promise((resolve, reject) => {
fetch(url, init)
.then(resolve)
.catch(reject);
setTimeout(reject, timeout);
}}
...或也许Promise.race()
首先获取或超时完成时使用哪个解析,例如:
Promise.race([
fetch('http://url', { method: 'GET' }),
new Promise(resolve => setTimeout(resolve, 3000))
])
.then(response => console.log(response))
Aborting a Fetch {#abortingafetch}
轻松终止XHR请求,xhr.abort()
并在必要时使用xhr.onabort
功能检测此类事件。
几年来无法中止Fetch,但是现在实现AbortController API的浏览器支持它。这将触发一个信号,该信号可以传递给Fetch启动对象:
const controller = new AbortController();
fetch(
'http://domain/service',
{
method: 'GET'
signal: controller.signal
})
.then( response => response.json() )
.then( json => console.log(json) )
.catch( error => console.error('Error:', error) );
可以通过调用中止获取controller.abort();
。Promise拒绝,因此.catch()
调用该函数。
No Progress {#noprogress}
在撰写本文时,Fetch不支持进度事件。因此,不可能报告文件上传或类似的大型表单提交的状态。
XMLHttpRequest与Fetch API?
最终,选择是您自己的...... 除非您的应用程序具有要求上载进度条的IE客户端。
对于更简单的Ajax调用,它XMLHttpRequest
是较低级别的,更复杂的,并且您将需要包装函数。不幸的是,一旦您开始考虑超时,调用中止和错误陷阱的复杂性,Fetch也会如此。
您可以选择将Fetch polyfill与Promise polyfill结合使用,以便可以在IE中编写Fetch代码。但是,XHR被用作备用。并非每个选项都能按预期工作,例如,无论设置如何,都会发送Cookie。
获取是未来。但是,该API是相对较新的,它不提供所有XHR功能,并且某些选项比较繁琐。在接下来的几年中请谨慎使用。
总结
总而言之,XMLHttpRequest和Fetch API,对于我们Web前端工程师,都必须掌握,不同场景,不同项目,好自用之即可。