专注营销系统开发11年为企业开拓营销空间!

微信小程序工具|微信小程序开发|微信小程序制作平台-龙图应用【XcxIP.com】

多年微信小程序专业开发商
中国行业十佳诚信企业、质量、服务

全国咨询热线15321026642

新闻资讯

新闻资讯
当前位置:网站首页>新闻资讯

微信小程序resolve原理详解,异步回调不再头疼

发布时间:10-17来源:微信小程序工具|微信小程序开发|微信小程序制作平台-龙图应用【XcxIP.com】

写小程序的时候,你是不是也遇到过这种场景:明明数据请求发出去了,页面却一片空白,等半天才反应过来是回调没处理好。特别是刚接触小程序开发的朋友,看到代码里层层嵌套的success、fail回调,头皮都发麻。其实问题没那么复杂,微信小程序里的resolve就是那把钥匙,只是很多人没用对地方。

微信小程序resolve原理详解,异步回调不再头疼

先搞清楚一个基本概念:resolve是Promise对象里的方法,它的作用是告诉系统“我这边的异步操作搞定了,你可以继续往下走了”。在小程序里,不管是wx.request网络请求,还是wx.getStorage读取缓存,本质上都是异步操作。你不可能让用户等数据回来再渲染页面,那体验太糟糕了。所以小程序把这些操作封装成Promise,通过resolve和reject来通知外部代码结果。

我见过不少开发者,在小程序里写异步代码还是老一套:success回调里套success回调,三层嵌套下来,代码自己都认不出自己。比如要获取用户信息,然后根据信息去请求列表,再处理列表数据,这要写三个success,中间任何一步出错都很难排查。这时候resolve就派上用场了——你可以把整个流程拆成一个链式结构,每一步返回一个Promise,通过resolve把数据传给下一步。

具体怎么用呢?给你看个例子。假设你要先登录获取code,然后拿code去换openid,用openid请求用户数据。传统写法是三个回调嵌套,用resolve改写后就清晰多了:第一个函数返回一个Promise,resolve把code传出去;第二个函数接收code,再返回一个新Promise,resolve把openid传出去;第三个函数接收openid,处理完数据后resolve。这样写的好处是,每一步都在同一层,不用往深处缩进,出错时也能精确定位到是哪一步出了问题。

但这里有个坑,很多人没注意到。resolve只是告诉Promise“成功了”,但如果你在resolve之前代码抛了异常,这个Promise永远不会进入成功状态,后续的then也不会执行。所以写小程序异步逻辑时,一定要记得在可能出错的地方加上try-catch,或者在Promise里用reject把错误传出去。不然你debug的时候会发现,明明没报错,但数据就是不出来,卡在某个resolve前面,找半天找不到原因。

再往深了说,resolve在小程序里还有个妙用,就是配合async/await。虽然Promise的then链已经比回调清晰多了,但遇到复杂业务逻辑,then链写长了还是会乱。这时候把函数声明成async,内部用await等待Promise完成,代码看起来就跟同步的一样。比如上面那个登录流程,用async/await写就是:const code = await login(),然后const openid = await getOpenid(code),const userData = await getUserData(openid)。每一行都清清楚楚,不用再靠then来传值。

不过我得提醒你,async/await虽然好用,但别滥用。有些场景下,多个请求之间没有依赖关系,比如同时获取首页的banner和商品列表,你如果老老实实await一个再await另一个,那白白浪费了时间。这时候应该用Promise.all,把两个请求同时发出去,等全部resolve后再统一处理。在小程序里,这种并行请求很常见,尤其是首页这种数据来源多的地方,用Promise.all能把加载时间缩短一半。

还有一个细节,很多人写resolve的时候,喜欢把整个数据对象传出去,比如resolve(res.data)。这在小程序里没问题,但我建议你传出去之前先做一层数据清洗。因为wx.request返回的res.data里包含了状态码、消息、具体数据等多个字段,你全传出去,后面每个环节都要去判断statusCode,代码重复不说,还容易漏判断。不如在源头处理一下,只把需要的数据resolve出去,后面用起来干净利落。

另外,小程序里有些API本身不支持Promise,只能用回调。比如wx.getSystemInfoSync这种同步接口还好,但像wx.chooseImage这种,老版本只支持success回调。这时候你可以自己包一层,把回调封装成Promise,内部用resolve处理成功分支。这样整个项目里的异步代码风格就统一了,不会一会Promise一会回调,看着别扭。

说到这,就不得不提一个常见误区。有人觉得resolve了就算完事,不管后续逻辑了。其实resolve只是信号,真正干活的是then或await后面的代码。如果你resolve之后还有同步操作要执行,比如更新页面数据、关闭加载动画,这些应该放在resolve调用之后,但要注意执行顺序。在小程序里,页面数据更新需要用setData,而setData本身也是异步的,如果你在resolve后立刻setData,可能数据还没渲染出来,用户看到的还是旧界面。

我建议的做法是,在resolve之前把该准备的都准备好,包括计算好要展示的数据格式,然后在then或await之后只做setData和UI更新的操作。这样逻辑清晰,也不容易出问题。而且,小程序有性能优化机制,频繁setData会触发视图层更新,如果你在resolve后多次setData,可能造成页面闪烁,影响体验。所以尽量把数据整合好,一次setData搞定。

想说的是,resolve这个API本身不复杂,复杂的是你怎么用它来组织代码。小程序开发里,异步操作躲不开,与其每次碰到都临时硬写,不如花点时间把项目里的异步模式规范起来。该用Promise的地方用Promise,该用async/await的地方用async/await,该并行的时候并行,该串行的时候串行。等这些习惯养成了,你会发现回调地狱其实没那么可怕,resolve用好了,异步回调这块就不再让你头疼了。

分享到:0 用手机看
微信小程序resolve原理详解,异步回调不再头疼

拍下二维码,信息随身看

试试用手机扫一扫,
在你手机上继续观看此页面。