数据对接

目前我们使用两种标准前端页面方法进行数据对接,他们是 Ajax 和 WebSocket ,本章我们将详细介绍这两种方式进行数据对接:

Ajax 方式对接

Ajax 数据对接

Ajax 的本质是通过浏览器的 XMLHttpRequest 对象向服务器发送 HTTP 请求,得到服务器返回的数据后进行数据处理的数据交互方式。

对于原生的 Ajax 来说,包括以下几个步骤:

  1. 创建 XMLHttpRequest 实例;
  2. 发出 HTTP 请求;
  3. 接收服务器传回的数据;
  4. 处理数据,更新页面。

在 ThingJS 在线开发环境中,内置了 JQuery 库,可以直接使用 JQurey 封装的 Ajax 方法进行数据对接,例如:

$.ajax({
    'url': "http://3dmmd.cn:83/getMonitorDataById", //Ajax请求服务的地址
    'type': "GET", //请求方式 "POST" 或 "GET",默认为 "GET"
    'dataType': "json",    //服务返回的数据类型,推荐使用标准JSON数据格式
    //发送到服务器的数据
    'data': { 'id': 89757 },
    //请求成功后的回调函数
    'success': function (data) {
        console.log(data);
        // 处理返回的数据
    },
    //请求失败时调用的函数 有以下三个参数:XMLHttpRequest 对象、错误信息、(可选)捕获的异常对象
    'error': function (xhr, status, error) {
        console.log(xhr);
    },
}); 

关于跨域

浏览器出于安全考虑,有同源策略(same-origin policy),所谓“同源”指的是“三个相同”:

  • 协议相同;
  • 域名相同
  • 端口相同

对于 ThingJS 在线开发环境所发布的 3D 页面而言,其协议是 https:// ,域名是 www.thingjs.com ,端口是 80 (默认端口可以省略),如果协议、域名或者端口有一个不同就是跨域,Ajax 请求就会失败。

在开发工具 Network 中可查看请求情况,下图展示了跨域相关报错:

因此,要在 ThingJS 在线环境中请求用户自己服务器上的静态资源数据或数据服务,或者其他网站的数据服务,就需要解决跨域问题。

help
注意事项

如果是访问用户上传到 ThingJS 网站的静态 json 数据资源则不存在跨域问题。

Ajax 请求跨域解决方案

对于在 ThingJS 在线开发环境中开发,我们推荐以下两种方案解决跨域问题:

  • CORS;

    CORS 是一个 W3C 标准,全称是 “跨域资源共享”(Cross-origin resource sharing)。它允许浏览器向跨域的服务器,发出 XMLHttpRequest 请求,从而解决了 Ajax 跨域请求数据的问题。

    对于前端而言,整个 CORS 通信过程,由浏览器自动完成。对于开发者来说,前端代码与普通 Ajax 代码完全一样。实现 CORS 的关键是后端,需在服务端设置 response 响应头(header)的 Access-Control-Allow-Origin 属性就可以开启 CORS。该属性表示哪些域名可以访问资源,如果设置通配符则表示所有网站都可以访问资源,例如:

    "Access-Control-Allow-Origin", "*" //所有网站都可访问
    // 仅ThingJS网站能访问
    // "Access-Control-Allow-Origin","http://www.thingjs.com"
     

    如果 CORS 请求不是简单的跨站请求,如:

    • 使用GET或POST以外的HTTP请求方法(PUT DELETE等);
    • 请求的Content-Type 不属于以下三种之一:
      • application/x-www-form-urlencoded;
      • text/plain;
      • multipart/form-data;
    • 发送了自定义的请求头信息(如Token数据)。

      那么还需根据实际情况,在服务器的响应头中设置 Access-Control-Allow-Headers 和Access-Control-Allow-Methods 相关属性值,例如:

      浏览器 Ajax 请求为:

      $.ajax({
          'headers': {
              "token": '31415926'// 请求头中带上了token数据
          },
          'url': "http://localhost:3000/getDataByIds",
          'type': "POST",
          //发送数据到服务器时所使用的内容类型。默认是:"application/x-www-form-urlencoded" 但此方式无将复杂的 JSON 组织成键值对形式
          //因此设置 contentType 为'application/json; charset=utf-8',这种类型是文本类型
          'contentType': 'application/json; charset=utf-8',
          'dataType': "json",
          //发送到服务器的数据 由于contentType设置为'application/json; charset=utf-8',这里需将json对象转为字符串后发送
          'data': JSON.stringify({ 'ids': [1, 2, 3] }),
          'success': function (data) {
              console.log(data);
          }
      }); 

      则服务端需要设置:

      //配置允许的请求方式,如果写 * 则都允许
      "Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS";
      //配置允许的自定义请求头,如果写 * 则都允许
      "Access-Control-Allow-Headers", "Content-Type,Token" 
  • JSONP

    JSONP 的基本原理就是利用 script 标签没有跨域限制的特点,通过 script 标签向服务器请求数据;服务器收到请求后,将数据放在一个指定名字的回调函数里返回给浏览器。

    help
    注意事项

    JSONP 仅支持 GET 请求。

    由于 JQuery 的 Ajax 请求对 JSONP 进行了封装,因此我们可以直接使用相关方法请求 JSONP 数据,例如:

    $.ajax({
    type: "get",
    url: "http://3dmmd.cn:83/monitoringData",
    data: { "id": 89757},
    dataType: "jsonp",// 返回的数据类型,设置为JSONP方式
    //设置回调函数名 JQurey会自动注册该函数
    jsonpCallback: "myCallbackFun",
    success: function (d) {
        console.log(d);
    // 处理json数据
    }
    }); 

    上述示例会向浏览器发送一个类似 http://3dmmd.cn:83/monitoringData?id=89757&callback=myCallbackFunc 的请求,服务器通过解析 url 中的 callback 参数,返回如下数据:

    myCallbackFunc({
    "state": "success",
    "data": {
        "id": "89757",
        "temper": "26℃",
        "humi": "42%",
        "power": "9kWh"
    }}
    ) 

    请求成功后 JQuery 会执行 myCallbackFun 函数,从而可以在回调函数中得到并处理 json 数据。

    help
    注意事项

    用 JQuery 的 Ajax 方法 发起多个 jsonp 请求时,回调函数名不要重复(即 jsonpCallback 的设置不要重复),否则可能会导致回调函数 undefined ,详见 https://www.cnblogs.com/lenghan/p/5777588.html 。

对于 ThingJS 在线开发环境所发布的 3D 页面而言,其协议是 https:// ,域名是 www.thingjs.com ,端口是 80 (默认端口可以省略),如果协议、域名或者端口有一个不同就是跨域,Ajax 请求就会失败。

在开发工具 Network 中可查看请求情况,下图展示了跨域相关报错:

因此,要在 ThingJS 在线环境中请求用户自己服务器上的静态资源数据或数据服务,或者其他网站的数据服务,就需要解决跨域问题。

help
注意事项

如果是访问用户上传到 ThingJS 网站的静态 json 数据资源则不存在跨域问题。

$.ajax({
    'url': "http://3dmmd.cn:83/getMonitorDataById", //Ajax请求服务的地址
    'type': "GET", //请求方式 "POST" 或 "GET",默认为 "GET"
    'dataType': "json",    //服务返回的数据类型,推荐使用标准JSON数据格式
    //发送到服务器的数据
    'data': { 'id': 89757 },
    //请求成功后的回调函数
    'success': function (data) {
        console.log(data);
        // 处理返回的数据
    },
    //请求失败时调用的函数 有以下三个参数:XMLHttpRequest 对象、错误信息、(可选)捕获的异常对象
    'error': function (xhr, status, error) {
        console.log(xhr);
    },
}); 

WebSocket对接

WebSocket 是 HTML5 一种新的协议,实现了浏览器与服务器之间的全双工通信。

其本质是先通过 HTTP/HTTPS 协议进行握手后创建一个用于交换数据的 TCP 连接,服务端与客户端通过此 TCP 连接进行数据的双向实时传输,直到有一方主动发送关闭连接请求或出现网络错误才会关闭连接。

WebSocket 最大的优点在,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,真正实现了数据的实时双向通信。并且 WebSocket 通信不受同源策略的限制,即不存在跨域问题。

WebSocket 客户端 API

浏览器端的一个简单示例如下:

// 创建一个WebSocket连接
var webSocket = new WebSocket('ws://3dmmd.cn:82');
// 建立 websocket 连接成功 触发open事件
webSocket.onopen = function () {
    console.log("websocket服务器连接成功...");
};

// 接收服务端数据 触发message事件
webSocket.onmessage = function (ev) {
    console.log("websocket接收到的数据:" + ev.data);
};
// 关闭连接后 触发close事件
webSocket.onclose = function (evt) {
    console.log("websocket关闭...");
};
// 通信发生错误时 触发error事件
webSocket.onerror = function () {
    console.log('发生错误')
} 

可通过 readyState 属性值(只读),获取连接状态:

  • 0 - 表示连接尚未建立;
  • 1 - 表示连接已建立,可以进行通信;
  • 2 - 表示连接正在进行关闭
  • 3 - 表示连接已经关闭或者连接不能打开

当连接成功后,可利用 send() 方法向服务器发送数据,例如:

var dataObj = { 'id': 89785 };
// send 数据类型可以是 字符串 或 二进制对象(Blob 对象、ArrayBuffer 对象)
webSocket.send(JSON.stringify(dataObj)); 

在客户端可调用 close() 方法主动关闭 WebSocket 连接。

WebSocket 服务器端

在服务器端,Node.js、Java、.Net、C++ 等语言都有相应的 API 库或框架来实现 WebSocket 的服务端开发。开发者可根据具体的项目需求选择相应方案,这里不再详细说明。

在线咨询
QQ交流群
微信公众号