• 如何封装js来调用各开放平台打印组件,实现同步效果


    淘宝,京东,抖音,快手 ,拼多多,微信等相继提供了电子面单服务。

    商家下载打印组件,通过报文和打印组件交互就可以实现密文订单的打印。

    我们作为web开发者,在打单过程需要处理各种事件和逻辑,如何实现流程的顺序(同步)成为一个关注问题。

    我们以京东打印组件为例,

    首先阅读文档:京东物流开放平台

    可知,需要websockt和打印组件交互。熟悉socet开发的人,写此类代码游刃有余。

    本篇对刚入手的人可以作为参考。

    1、第一步,通过消息订阅模型来处理socket接收的消息

         将收的消息根据消息报文进行分类,然后和请求消息进行对应,

         从而将异步发送和接收关联起来。

    2、第二步,通过es6的promise实现同步处理效果

         让发送和接收 通过promsie关联,接收成功触发resolve,从而将发送和接收代码放到一起。

    3、第三步,async 关键字

        通过async定义函数,内部用await,可实现多个异步请求串行化出(逻辑串行话)

    4、代码示例

    1. //MyJdPrinter.js
    2. export function MyJdPrinter() {
    3. var jdSocket;
    4. this.connect = function (fnOpen, fnClose, fnError) {
    5. /* if (this.socketStatus == "CONNECTION_STATUS_CONNECTIONED") {
    6. fnError({status: this.socketStatus, msg: "当前已连接,操作已取消"});
    7. }*/
    8. if (this.socketStatus == "CONNECTION_STATUS_CONNECTIONED") {
    9. fnOpen(null,{msg:"当前已连接,操作已取消",socketStatus});
    10. return;
    11. }
    12. if (this.socketStatus == "CONNECTION_STATUS_CONNECTING") {
    13. fnError({status: this.socketStatus, msg: "其他连接正在执行,操作已取消"});
    14. return;
    15. }
    16. this.connected=true;
    17. _doConnect(fnOpen, fnClose, fnError);
    18. lastFnOpen = fnOpen;
    19. lastFnClose = fnClose;
    20. lastFnError = fnError;
    21. }; //end connect()
    22. /**
    23. * 获取打印机列表:{cmd: 'getPrinters', defaultPrinter: '', msg: '成功', printers:[{name,status,type}], "requestID": 1,"status": "success"}
    24. * @returns {Promise}
    25. */
    26. this.checkStatus = function () {
    27. FN_UID++;
    28. var requestId = FN_UID;
    29. //用于回调,需要和报文中一直
    30. var requestCmd = CMD["6"];//6
    31. if (this.socketStatus == "CONNECTION_STATUS_UNCONNECT") {
    32. Promise.reject("未连接");
    33. }
    34. return new Promise((resolve, reject) => {
    35. var p = _genExecutorParam(requestId, requestCmd, resolve);
    36. executorList.push(p);
    37. _sendGetPrinters(requestId);
    38. });
    39. };//end checkStatus
    40. }

    调用实例:

    var jdPrinter = new MyJdPrinter(); //仅仅创建实例

    //由于我们可能多个地方需要获取实例,不能每次都连接,所以MyJdPrinter内部需要缓存实例。

    1. function _doConnect(fnOpen, fnClose, fError) {
    2. //这里对象创建不报错,异步连接会报错,onerror来处理
    3. jdSocket = new WebSocket('ws://localhost:9113');
    4. jdSocket.onopen = function (event) {
    5. //clearTimeout(timeout);
    6. THIS.socketStatus = "CONNECTION_STATUS_CONNECTIONED";
    7. fnOpen(event);
    8. // 监听Socket的关闭
    9. jdSocket.onclose = function (event) {
    10. THIS.socketStatus = "CONNECTION_STATUS_UNCONNECT";
    11. fnClose(event);
    12. };
    13. };
    14. //{isTrusted: true, type: 'error', target: WebSocket, currentTarget: WebSocket, eventPhase: 2, …}
    15. jdSocket.onerror = function (evt) {
    16. fError(evt);
    17. };
    18. // 监听消息
    19. jdSocket.onmessage = function (event) {
    20. var data = JSON.parse(event["data"]);
    21. /*
    22. {
    23. "code": "6",
    24. "content": "Microsoft Print to PDF,导出为WPS PDF,OneNote for Windows 10,pdfFactory Pro,Microsoft XPS Document Writer,Fax",
    25. "detailinfo": {
    26. "printers": [
    27. "Microsoft Print to PDF",
    28. "导出为WPS PDF",
    29. "OneNote for Windows 10",
    30. "pdfFactory Pro",
    31. "Microsoft XPS Document Writer",
    32. "Fax"
    33. ]
    34. },
    35. "key": "1",
    36. "message": "get printers success",
    37. "status": "500",
    38. "success": "true"
    39. }
    40. */
    41. var requestID = data["key"];
    42. var cmd = data["code"];
    43. //循环 {fnUid,fnCmd,fnResolve}
    44. var finded = false;
    45. executorList.forEach(function (executor) {
    46. //这里根据id判断
    47. if (executor["fnUid"] == requestID) {
    48. executor["fnResolve"](data);
    49. finded = true;
    50. return;
    51. }
    52. });
    53. if (!finded) {
    54. console.log(`消息未识别,cmd=${cmd}`, event);
    55. }
    56. //console.log('Client received a message', event);
    57. };
    58. }

    获取缓存实例,只有断开时需要重连,否则connect应该只调用一次即可。

    1. local["fn"]["getMyJdPrinter"]= function () {
    2. let jdPrinter =local["ins"]["insMyJdPrinter"];
    3. if (jdPrinter["connected"]==false){
    4. var promise = new Promise((resolve, reject)=>{
    5. jdPrinter.connect(()=>{
    6. resolve(jdPrinter);
    7. },()=>{
    8. console.log("连接关闭,重新连接");
    9. jdPrinter.reConnect();
    10. },()=>{
    11. console.log("连接失败,重新连接");
    12. jdPrinter.reConnect();
    13. });
    14. });
    15. return promise;
    16. }
    17. return Promise.resolve(jdPrinter);
    18. };

    如上,我们再封装一个公共方法,来执行首次connect以及绑定重连函数。

    通过以上primsise方式+async关键字就可以实现异步请求串行化。

    以上是个人思路,大家有更好的写法或实例,欢迎留言或私信,相互学习。

  • 相关阅读:
    怎样下载国内外专利?
    TDengine3.0流式计算引擎语法规则介绍
    老卫带你学---leetcode刷题(344. 反转字符串)
    chrome事件循环的自问自答
    《最新出炉》系列初窥篇-Python+Playwright自动化测试-37-如何截图-上篇
    VMware Fusion 13在M2芯片的Mac上安装 Windows 11
    惊帆JF141心率血氧模块简单使用(STM32标准库代码)
    c++通过tensorRT调用模型进行推理
    (Java高级教程)第一章Java多线程基础-第一节4:synchronized关键字(监视器锁monitor lock)和volatile关键字
    领域事件和集成事件没那么高大上
  • 原文地址:https://blog.csdn.net/hvang1988/article/details/134331419