面向Promise编程:避免使用try catch
现在,我们尝试将DataServiceViaFileSystemManager类的代码改造一下,来看一下不使用工具方法promisify,直接使用同步接口实现是什么样子,如代码清单1-11所示。
代码清单1-11 使用同步接口实现文件读写
消费代码不需要修改,重新编译测试,运行输出与之前没有差别。
与DataServiceViaFileSystemManager相比,DataServiceViaFileSystemManager2的代码是类似的,区别在于第23行、第43行不再使用工具方法promisify,而是直接调用对应的同步接口:#fsMgr.writeFileSync和#fsMgr.accessSync。问题就可能出现在这两个同步接口上。
这两个同步接口在被调用时,可能会爆出以下5种异常。
❑fail no such file or directory, open${filePath}:指定的filePath所在目录不存在。
❑fail permission denied, open${dirPath}:指定的filePath路径没有写权限。
❑fail the maximum size of the file storage limit is exceeded:存储空间不足。
❑fail sdcard not mounted Android sdcard:挂载失败。
❑fail no such file or directory${path}:文件/目录不存在。
这些异常是小游戏运行时环境以throw的方式抛出的,不是以运行时接口调用结果的形式返回的,处理这些异常必须使用try catch语句(见第21行、第40行)。但是try catch会让代码看起来不简洁,嵌套多,好的代码是不应该使用try catch的。(事实上从运行效率来讲,try catch需要更多的运行时开销,建议慎重使用。)
这是我们在前面提到的,在DataServiceViaFileSystemManager类中使用工具方法promisify进行接口转化,宁愿使用#fsMgr.writeFile和#fsMgr.access这两个同步版本,也不使用#fsMgr.writeFileSync和#fsMgr.accessSync这两个异步版本的原因。
最后总结一下,我们应当如何选择并使用微信小程序/小游戏平台的异步接口和同步接口。
❑对于提供了Promise风格调用能力的异步接口,直接加await调用。
❑对于没有Promise风格调用能力的异步接口,看有没有同步接口,即异步接口名称后面是否存在带Sync后缀的接口。如果存在,再看有没有可能抛出异常:如果可能,则放弃使用,改用工具方法promisify转换异步接口;如果不可能,再放心大胆地使用带Sync后缀的同步接口。
至于如何判断同步接口会不会抛出异常,可以查看官方文档,文档中都有详细描述。
注意
以上关于异步接口、同步接口选择策略的示例演示,是基于小游戏基础库2.19.5的,不排除以后基础库版本升级后同步接口不再抛出异常的可能,如果那样的话,使用同步接口也无妨。微信小程序/小游戏的基础库及微信开发者工具自上线以来一直在快速进化,我们在开发时把握基本的原理和准则就可以了。
现在看一下DataServiceViaFileSystemManager和DataServiceViaFileSystemManager2这两个类的第三个方法:clearLocalData。在测试中我们会发现,clearLocalData好像永远都不会成功。如果路径有误,可能会在调试区看到这样一个错误:
如果路径没有问题,则什么都不会返回,但文件依然存在。这是为什么呢?
这是因为通过FileSystemManager.removeSavedFile接口只能删除通过FileSystemManager.saveFile保存的文件,saveFile接口的用途是将临时文件转存为在用户空间中永久存储的文件。我们的记分数据文件并不是通过saveFile接口保存的,因此也无法通过removeSavedFile接口删除。
在测试中,如果想清除通过writeFile或writeFileSync保存的文件,可以在微信开发者工具中依次选择“清缓存”→“清除文件缓存”选项。