淘宝,京东,抖音,快手 ,拼多多,微信等相继提供了电子面单服务。
商家下载打印组件,通过报文和打印组件交互就可以实现密文订单的打印。
我们作为web开发者,在打单过程需要处理各种事件和逻辑,如何实现流程的顺序(同步)成为一个关注问题。
我们以京东打印组件为例,
首先阅读文档:京东物流开放平台
可知,需要websockt和打印组件交互。熟悉socet开发的人,写此类代码游刃有余。
本篇对刚入手的人可以作为参考。
1、第一步,通过消息订阅模型来处理socket接收的消息
将收的消息根据消息报文进行分类,然后和请求消息进行对应,
从而将异步发送和接收关联起来。
2、第二步,通过es6的promise实现同步处理效果
让发送和接收 通过promsie关联,接收成功触发resolve,从而将发送和接收代码放到一起。
3、第三步,async 关键字
通过async定义函数,内部用await,可实现多个异步请求串行化出(逻辑串行话)
4、代码示例
- //MyJdPrinter.js
- export function MyJdPrinter() {
- var jdSocket;
-
- this.connect = function (fnOpen, fnClose, fnError) {
-
- /* if (this.socketStatus == "CONNECTION_STATUS_CONNECTIONED") {
- fnError({status: this.socketStatus, msg: "当前已连接,操作已取消"});
- }*/
- if (this.socketStatus == "CONNECTION_STATUS_CONNECTIONED") {
- fnOpen(null,{msg:"当前已连接,操作已取消",socketStatus});
- return;
- }
-
-
- if (this.socketStatus == "CONNECTION_STATUS_CONNECTING") {
- fnError({status: this.socketStatus, msg: "其他连接正在执行,操作已取消"});
- return;
- }
- this.connected=true;
- _doConnect(fnOpen, fnClose, fnError);
- lastFnOpen = fnOpen;
- lastFnClose = fnClose;
- lastFnError = fnError;
-
-
- }; //end connect()
-
- /**
- * 获取打印机列表:{cmd: 'getPrinters', defaultPrinter: '', msg: '成功', printers:[{name,status,type}], "requestID": 1,"status": "success"}
- * @returns {Promise
} - */
- this.checkStatus = function () {
- FN_UID++;
- var requestId = FN_UID;
- //用于回调,需要和报文中一直
- var requestCmd = CMD["6"];//6
-
- if (this.socketStatus == "CONNECTION_STATUS_UNCONNECT") {
- Promise.reject("未连接");
- }
- return new Promise((resolve, reject) => {
- var p = _genExecutorParam(requestId, requestCmd, resolve);
- executorList.push(p);
- _sendGetPrinters(requestId);
-
- });
- };//end checkStatus
-
- }
调用实例:
var jdPrinter = new MyJdPrinter(); //仅仅创建实例
//由于我们可能多个地方需要获取实例,不能每次都连接,所以MyJdPrinter内部需要缓存实例。
- function _doConnect(fnOpen, fnClose, fError) {
- //这里对象创建不报错,异步连接会报错,onerror来处理
- jdSocket = new WebSocket('ws://localhost:9113');
- jdSocket.onopen = function (event) {
- //clearTimeout(timeout);
- THIS.socketStatus = "CONNECTION_STATUS_CONNECTIONED";
- fnOpen(event);
-
- // 监听Socket的关闭
- jdSocket.onclose = function (event) {
- THIS.socketStatus = "CONNECTION_STATUS_UNCONNECT";
- fnClose(event);
- };
- };
- //{isTrusted: true, type: 'error', target: WebSocket, currentTarget: WebSocket, eventPhase: 2, …}
- jdSocket.onerror = function (evt) {
- fError(evt);
- };
- // 监听消息
- jdSocket.onmessage = function (event) {
- var data = JSON.parse(event["data"]);
- /*
- {
- "code": "6",
- "content": "Microsoft Print to PDF,导出为WPS PDF,OneNote for Windows 10,pdfFactory Pro,Microsoft XPS Document Writer,Fax",
- "detailinfo": {
- "printers": [
- "Microsoft Print to PDF",
- "导出为WPS PDF",
- "OneNote for Windows 10",
- "pdfFactory Pro",
- "Microsoft XPS Document Writer",
- "Fax"
- ]
- },
- "key": "1",
- "message": "get printers success",
- "status": "500",
- "success": "true"
- }
- */
- var requestID = data["key"];
- var cmd = data["code"];
- //循环 {fnUid,fnCmd,fnResolve}
- var finded = false;
- executorList.forEach(function (executor) {
- //这里根据id判断
-
- if (executor["fnUid"] == requestID) {
- executor["fnResolve"](data);
- finded = true;
- return;
- }
- });
- if (!finded) {
- console.log(`消息未识别,cmd=${cmd}`, event);
- }
- //console.log('Client received a message', event);
- };
- }
获取缓存实例,只有断开时需要重连,否则connect应该只调用一次即可。
- local["fn"]["getMyJdPrinter"]= function () {
- let jdPrinter =local["ins"]["insMyJdPrinter"];
- if (jdPrinter["connected"]==false){
- var promise = new Promise((resolve, reject)=>{
- jdPrinter.connect(()=>{
- resolve(jdPrinter);
- },()=>{
- console.log("连接关闭,重新连接");
- jdPrinter.reConnect();
- },()=>{
- console.log("连接失败,重新连接");
- jdPrinter.reConnect();
- });
- });
- return promise;
- }
- return Promise.resolve(jdPrinter);
- };
如上,我们再封装一个公共方法,来执行首次connect以及绑定重连函数。
通过以上primsise方式+async关键字就可以实现异步请求串行化。
以上是个人思路,大家有更好的写法或实例,欢迎留言或私信,相互学习。