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

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

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

我们作为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关键字就可以实现异步请求串行化。

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

你可能感兴趣的:(javascript,前端,开发语言)