淘宝,京东,抖音,快手 ,拼多多,微信等相继提供了电子面单服务。
商家下载打印组件,通过报文和打印组件交互就可以实现密文订单的打印。
我们作为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关键字就可以实现异步请求串行化。
以上是个人思路,大家有更好的写法或实例,欢迎留言或私信,相互学习。