从五年前的前端老代码中,学到的编码小技巧~

程序员他爱做梦 2024-02-23 03:53:54
背景

最近在看一个比较老的工具库源码,学到了一点代码的小技巧,我觉得对于以后的异步操作开发来说挺有用的,所以今天写了一篇文章,分享给大家~

例子

假设,现在有一个类,这个类维护了一个db对象,但是这个db对象需要通过异步操作(请求)并拿到结果,来进行初始化,且我们需要用到db对象上的get方法,来进行数据的获取,请看下方简易代码~

const request = () => { return new Promise(resolve => { // 模拟请求后得到db对象 setTimeout(() => { resolve({ get: key => key, }); }, 300); });};class DB { private db; constructor() { this.init(); } init() { return request().then(res => { this.db = res; }); } getItem() { console.log(this.db.get('info')); }}

接着我们进行实例的创建,并使用getItem方法去执行db对象身上的get方法,获取我们想要的数据,但是此时会引起报错,说db不存在

const base = new Base();base.getItem(); // 报错:this.db 不存在

这是因为db是通过异步获取的,当你执行getItem的时候,db 还没初始化完成呢,所以我们得换一种写法我们需要保证init异步执行完成,再去执行后面的getItem,这样才不会报错

class Base { private db; init() { return request().then(res => { this.db = res; }); } getItem() { console.log(this.db.get('info')); }}const fn = async () => { const base = new Base(); await base.init(); base.getItem(); // 'info'};

改进

但是这样其实也不是好的做法,按理说init最好是不要去主动执行,而是应该写在内部,而且把异步init写在外面,又得套上async函数,非常麻烦,所以我们换一种写法。

大致思想就是,我们设置一个全局的promise,这个promise只有在初始化完成后,状态才会变成成功,才会执行 then 方法,然后对于 db 的操作,全都包裹在这个 promise 的 then 方法中,这样就能保证执行 db 身上方法时,db 已经被初始化完成了~

class Base { db; readyPromise; readyPromiseResolve; constructor() { this.init() } async init() { // 全局promise this.readyPromise = new Promise(resolve => { // 保存好全局resolve this.readyPromiseResolve = resolve }) return request().then(res => { this.db = res; // 初始化完成后执行全局resolve this.readyPromiseResolve() }); } ready() { // 获取全局promise return this.readyPromise } getItem() { // 全局promise执行then,说明已经初始化完成 // 这时候执行 getItem 就不会报错了 this.ready().then(() => { console.log(this.db.get('info')); }) }}const base = new Base();base.getItem() // 'info'

作者:Sunshine_Lin链接:https://juejin.cn/post/7281691679869468727

0 阅读:0

程序员他爱做梦

简介:感谢大家的关注