常青进级,js化解办法

时间:2019-10-10 00:55来源:编程技术
前言:此文在2018-1-7日已在「奎特尔星球」公众号上发布,但有简友留言询问有关protobuf在微信小游戏上的主题素材,再此将自己打听到的化解方式献上,供大家参考。 pbkiller1.0一度上线

前言:此文在2018-1-7日已在「奎特尔星球」公众号上发布,但有简友留言询问有关protobuf在微信小游戏上的主题素材,再此将自己打听到的化解方式献上,供大家参考。

pbkiller1.0一度上线Cocos商号,接济了微信小游戏碰到,笔者摄像了一段小录像,演示pbkiller的运用流程和办法。

protobufjs在微信小游戏碰着中运转出错,有时让多数个人被此主题材料卡住,做为pbkiller的开辟者,必得将些难点摸底精通,如今提供上面多少个方案:

pbkiller在微信小游戏中的使用

将proto文件调换为js文件使用,此措施支持protobufjs5.x澳门金莎娱乐网站,~6.x

在「奎特尔星球」除了介绍插件、工具以外,更首要的是将那一个插件、工具的落到实处原理和办法分享给大家,共同学习共同前行。

1.覆盖loadProtoFile方法

let ProtoBuf = require('protobufjs');ProtoBuf.Util.IS_NODE = cc.sys.isNative;ProtoBuf.loadProtoFile = function(filename, callback, builder) { if (callback && typeof callback === 'object') builder = callback, callback = null; else if (!callback || typeof callback !== 'function') callback = null; if  return cc.loader.load(typeof filename === 'string' ? filename : filename["root"]+"/"+filename["file"], function(error, contents) { if (contents === null) { callback(Error("Failed to fetch file")); return; } try { callback(error, ProtoBuf.loadProto(contents, builder, filename)); } catch  { callback; var contents = cc.loader.load(typeof filename === 'object' ? filename["root"]+"/"+filename["file"] : filename); return contents === null ? null : ProtoBuf.loadProto(contents, builder, filename);};

此方式是将ProtoBuf.Util.fetch函数替换到cc.loader.load函数,以消除在微信小游戏中不能够动用XHQashqai的标题。

本身以前在民众号上发过一篇《微信小游戏protobuf.js飞快化解办法》,在这里给我们说声不佳意思,那篇文章中的proto加载方案存在缺欠,具体难题如下图所示:

2.异步加载proto文件

现在加载proto文件须求运用异步格局

//创建一个共用的builder对象let builder = ProtoBuf.newBuilder();...ProtoBuf.loadProtoFile(filePath, (error, builder) => { let pb = builder.build(packageName); let player = new pb.Player(); player.name = 'zzz'; player.id = 123; let data = player.toArrayBuffer(); let player2 = pb.Player.decode; this.log;}, builder);

let protobuf = require(‘protobufjs’);protobuf.util.fetch = cc.loader.load.bind(cc.loader);

protobufjs 6.x动态加载,能够解决proto文件的加载难题,但protobufjs 6.x源码中使用了new Function() 函数动态变化代码,导致在实例化proto对象时微信会报错,此办法近年来不可取。

微信不支持XMLHTTPRequest API,而Protobuf中恰恰利用了此API,关键思路是利用cc.loader替代XMLHTTPRequest。

开拓微信小游戏时索要专一,微信开辟者工具的运维情形,在运用cc.loader.load、cc.loader.loadRes等函数时会常常出现回调不响应的场地,须要整个关门微信开辟者工具,或清空缓存再通过Creator运维游戏,有时可能会每每操作数次技艺见效。

自己付出的pbkiller插件,异步加载接口已经修改好了,照旧基于protobufjs5.x的卷入,使用方法基本不变。

澳门金莎娱乐网站 1

当a.proto文件中import了b.proto文件,在功成名就加载a.proto文件后protobufjs内部在分析a.proto时会自动加载b.proto,此时会触发XMLHttpRequest API的调用,导致在微信小游戏碰到出现错误。

一、protobuf.js加载源码剖析

抑或从protobuf.js源码出手,小编扩充了部分讲授,方便清楚:

ProtoBuf.loadProtoFile = function(filename, callback, builder) {
    //参数解析,检查callback参数是否有效
    if (callback && typeof callback === 'object') 
        builder = callback,
        callback = null;
    else if (!callback || typeof callback !== 'function')
        callback = null;
    //callback存在,使用异步加载
    if (callback)
        //使用ProtoBuf.Util.fetch函数异步加载,
        //注意这里的写法很不爽,调用fetch函数后立即return了
        return ProtoBuf.Util.fetch(typeof filename === 'string' ? filename : filename["root"]+"/"+filename["file"], function(contents) {
            if (contents === null) {
                callback(Error("Failed to fetch file"));
                return;
            }
            try {
                //加载成功,调用ProtoBuf.loadProto函数解析contents变量,转换为proto对象,通过callback函数返回
                callback(null, ProtoBuf.loadProto(contents, builder, filename));
            } catch (e) {
                callback(e);
            }
        });

    //callbcak不存在,使用同步方式,
    //通过ProtoBuf.Util.fetch的返回值,获取文件数据
    var contents = ProtoBuf.Util.fetch(typeof filename === 'object' ? filename["root"]+"/"+filename["file"] : filename);
    //加载成功,调用ProtoBuf.loadProto函数解析contents变量,转换为proto对象,通过return返回
    return contents === null ? null : ProtoBuf.loadProto(contents, builder, filename);
};

从源码中得以看看,protobufjs有三种加载方式:同步与异步。

在《当creator遇上protobufjs|相遇》 一文中我们分析过ProtoBuf.Util.fetch函数,这里大概回看一下:

浏览器:使用XMLHttpRequest落成的共同、异步的proto文件加载。

nodejs:异步使用fs.readFile,同步使用fs.readFileSync

Cocos-JSB:大家介绍了伪装fs模块的章程调用jsb.fileUtils.getStringFromFile来消除。

微信小游戏意况本身的知道是:阉割+定制过的浏览器,它未有提供XMLHttpRequest API,那是致使protobuf.js战败的缘故。

后来本身又尝试了在protobufjs 6.x中央银行使的方案,在ProtoBuf.loadProtoFile函数,使用cc.loader.load取代ProtoBuf.Util.fetch,选拔异步加载的章程,一样存在慰难点。

澳门金莎娱乐网站 2

在蒙受标题时,以个体的力量无法很好的化解时,去逛一逛论坛是二个不容置疑的主见。当自家把难题一提出,第二天就有一人ID叫a1990091的满腔热情朋友提供了二个思路:重写ProtoBuf.Util.fetch函数,在函数中反省当前是否为微信小游戏情状,然后能够应用微信提供的api去达成加载:

澳门金莎娱乐网站 3

此办法做的不行的大好,分别检查测量试验了JSB微信Web境况,提供分化的加载实现。可对本人来讲,的不满是pbkiller库对外直接提供的是一路加载方法,改为异步加载,对已经选拔pbkiller客商不太融洽,同步、异步如选取呢?

二、救命稻草cc.loader

发完帖从论坛回到难点上,不能够消除估算是睡不着了,头脑中一阵自言自语言,猛然想到cc.loader.getRes同步获取能源的接口与ProtoBuf.Util.fetch的一只方式同样,能不可能从此处出手吧?

在此间先简要介绍一下cc.loader下的多元load函数。

1. cc.loader.load(url, callback)

cc.loader.load的url参数是从项目揭露的根路线始于的全部路线,由此必要依据cc.url.raw函数来获取完整路线。

诸如:加载文件assets/resources/a.json

cc.loader.load(cc.url.raw('resources/a.json'), (error, json) => {
    cc.load(json);
});

cc.loader.load除了可以加载当前项目能源,更要紧的技术是加载别的远程服务器上的能源。只必要提交完整路径就能够,但在浏览器上选取供给小心跨域难题。

加载当前项目下resources目录下的能源,使用cc.loader.loadRes更为轻便。

越来越多用法请参考API文书档案:

2. cc.loader.loadRes(url, callback)

cc.loader.loadRes的url参数路线是以resources为根路线。

举例说:加载文件assets/resources/a.json

cc.loader.loadRes('a.json', (error, json) => {
    cc.load(json);
});

cc.loader.loadRes的用法比cc.loader.load轻巧非常多,也可能有没那么多参数重载的用法,API文书档案链接:

3. cc.loader.loadResDir(url, callback)

cc.loader.loadResDir看名就会猜到其意义它是加载一个索引(及子目录),url同样以assets/resources目录作为根路径。

诸如:加载文件 assets/resources/json目录下有a.json、b.json多少个文本

cc.loader.loadResDir('json', (error, array) => {
     //array中包含a.json和b.json的内容
    cc.log(array);
});

4. cc.loader.getRes(url)

cc.loader.getRes是cc.loader家族中头一无二的协同财富获取函数。可是它有叁个前提,供给被cc.loader.loadXXX加载成功过的能源才具应用,不然它会再次来到null。

比如:加载文件 assets/resources/json/a.json

//jsonA为null
let jsonA = cc.loader.getRes('json/a.json');
cc.loader.loadResDir('json', (error) => {
    //此时获取jsonB才有效    
    let jsonB = cc.loader.getRes('json/b.json');    
});

此处享用多个查看cc.loader缓存财富的一个艺术,在浏览器中运作你的品类,在调整调节台上输入:cc.loader._catch,你拜候到如下内容:

澳门金莎娱乐网站 4

cc.loader._catch对象中的全体财富,都得以采用cc.loader.getRes获取。讲到此处,笔者猜你已经大约知道怎么选择cc.loader.getRes搞定微信小游戏中proto的加载难题了。

三、cc.loader.getRes冯谖三窟

从剖判cc.loader的泛滥成灾加载函数,cc.loader.getRes去顶替ProtoBuf.Util.fetch,一样运用同步方式,那样pbkiller.loadAll/ pbkiller.loadFromFile的接口用法能够保险不改变。

要想cc.loader.getRes的重临值有效,供给事先将能源加载到cc.loader的缓存中,由此提供了贰个pbkiller.preload函数

let ProtoBuf = require('protobufjs');
preload(cb) {
    //运行时动态修改ProtoBuf.Util.fetch为cc.loader.getRes    
    ProtoBuf.Util.fetch = cc.loader.getRes.bind(cc.loader); 
    //使用cc.loader.loadResDir加载resources/pb目录所有文件    
    cc.loader.loadResDir('pb', (error, data) => { 
        //通知调用都,预加载完毕
        cb();
    }); 
}

粗略几行代码消除了富万分,並且从不改换protobuf.js任何一行源代码。再看下怎么着使用预加载函数:

/预先加载proto文件到引擎缓存
pbkiller.preload(() => { 
  //加载所有proto文件并动态生成proto对象
  let pb = pbkiller.loadAll();
  //实例化proto对象
  let player = new pb.grace.proto.msg.Player();
  ...
});

在实质上项目中能够提前实行pbkiller.preload,在此以前全体的pbkiller的用法保持不改变,利用javascript的动态属性赋值,非常是能够修改函数指针,基本上能够成功飞扬狂妄,况且无需修改源代码,有没有以为非常爽呢?

四、结语

pbkiller的基业是protobuf.js,小编所做的行事只是将protobuf.js适配到Cocos-JSB和微信小游戏情况,让其能健康工作。希望本人的经验能对你有着匡助,愿pbkiller能为您节省时间,升高功能!

编辑:编程技术 本文来源:常青进级,js化解办法

关键词:

  • 上一篇:没有了
  • 下一篇:没有了