前端/客户端的通信需求有多种,常见的业务需求有:请求服务器数据、主动推送数据、消息通知和文件上传。本文对比四种通信方式,针对业务需求分析最适合采用的通信方式。
fetch
请求服务器数据属于请求-响应式通信,是前端最常见的应用场景之一,先向服务器发送请求,收到服务器响应后获得数据。进入新页面时请求页面数据、点击视频时请求多媒体数据以及提交表单等行为都属于该场景。
fetch用于前端的网络请求,是传统XmlHttpRequest的改进替代方案。fetch对于异步请求网络资源有着优秀的返回处理机制,一个异步请求发出后,fetch会返回一个promise对象,根据请求结果将状态置为fulfilled或rejected,我们可以为promise对象指定回调函数。
fetch('http://example.com/movies.json')
.then(function(response) {
return response.json();
})
.catch(error => console.error('Error:', error))
.then(response => console.log('Success:', response));
复制代码
fetch在回调嵌套时的同步写法以及对CORS和HTTP扩展的原生支持,使得fetch成为请求-响应式通信的优先选择。在实际应用中,向服务器请求数据时适合采用fetch。
WebSocket
主动推送数据属于推送式通信,由前端向服务器,或服务器向客户端主动推送数据,不要求响应,比如客户端推送文本数据、服务器推送用户数据。 WebSocket与Ajax、fetch不同的是,不需要根据响应的success状态做针对处理,只负责推送数据。
const ws = new WebSocket("wss://localhost.websocket.org");
ws.onopen = function(evt) {
console.log("Connection open ...");
ws.send("Hello WebSockets!");
};
ws.onmessage = function(evt) {
console.log( "Received Message: " + evt.data);
ws.close();
};
ws.onclose = function(evt) {
console.log("Connection closed.");
};
复制代码
在主动推送场景中,WebSocket面向连接、性能高效且不受同源策略的限制,适合用于推送式通信。
ActiveMQ
消息通知属于消息-订阅式通信,一般由服务器向前端发送消息,消息只负责通知,不负责传输具体的数据,类似XmlHttpRequest中的请求头。
ActiveMQ是消息中间件,一般用来发送消息,不传输数据。
window.onload = function(){
const opts = {
url: www.hostMQ.com,
onConnected: (msg) => {
mqService.subscribe(`www.hostMQMessage.com`, function (frame) {
let message = JSON.parse(frame.body)
switch (message.messageType) {
case 'TypeA':
...
break
}
})
},
onError: (msg) => {
mqService.reconnect()
},
}
mqService.createBroker(opts)
}
复制代码
AcitveMQ发送的消息不要求响应,且支持订阅,因此适合用来做消息通知,例如多端同步消息。
reqwest.js
文件上传服务器也是前端的常见场景,上传大文件时需要把文件切割分片并通过FormData对象传输。这种场景要求灵活地处理每一片文件的上传结果,从而实现断点续传、上传进度显示等功能。
reqwest.js是Ajax的健壮版,reqwest.js的官方介绍上说“It's AJAX”。reqwest在GET请求、JSONP等写法上进行了改进。 reqwest的GET请求:
reqwest({
url: 'path/to/html'
, method: 'get'
, data: [ { name: 'foo', value: 'bar' }, { name: 'baz', value: 100 } ]
, success: function (resp) {
qwery('#content').html(resp)
}
})
复制代码
reqwest的JSONP请求:
reqwest({
url: 'path/to/data.jsonp?foo=bar'
, type: 'jsonp'
, jsonpCallback: 'foo'
, jsonpCallbackName: 'bar'
, success: function (resp) {
qwery('#content').html(resp.content)
}
})
复制代码
在文件传输时,reqwest.js不同于fetch的同步式回调,可以方便得指定每片文件上传成功或失败的回调函数。因此,在文件传输场景中reqwest是比fetch、Ajax更优先的选择。