Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Golang defer的Javascript实现 #163

Open
axetroy opened this issue Jan 10, 2018 · 0 comments
Open

Golang defer的Javascript实现 #163

axetroy opened this issue Jan 10, 2018 · 0 comments
Labels

Comments

@axetroy
Copy link
Owner

axetroy commented Jan 10, 2018

简单先说一下Go的defer特性:

  • defer是后进先出的原则执行
  • defer是在函数运行结束之后,才会运行

那么这些特性能干什么

  • 延迟任务
  • 尾部验证(比如运行函数之后,需要对返回值校验)
  • 资源销毁

一个具体的场景

在后端开发中,可能需要多人协作,多语言,多模块开发。这时候可能就需要用RPC通信

比如有个用户模块,在进入到一个业务的时候,你需要去验证用户是否合法

async function main(username) {
  const client = await rpc.createConnection(); // 创建RPC链接
  const data = await client.getUserInfo(username); // 通过RPC链接获取用户信息
  // 下面是业务逻辑
}

但是你发现,RPC链接并没有被关闭(即便函数执行完毕,对象client被销毁), 它依旧占用着服务端的资源,如果多次调用这个函数,会多服务端造成很大的压力.

解决方案有两个

  1. 维护连接池
  2. 在每次创建链接之后都销毁

第一种方法是大多数ORM,RPC框架做的,应用内只保持n个链接,不断的创建再销毁,而这个过程不用使用者关心。
很可惜的是,我选用的RPC框架Thrift,有屎一样的坑。为了保持和Go的业务逻辑一样,采用第二种方案,每次创建链接之后都销毁,保证它是干净的

依旧是上面的代码,改成这样

async function main(username) {
  const client = await rpc.createConnection(); // 创建RPC链接
  try{
    const data = await client.getUserInfo(username); // 通过RPC链接获取用户信息
    // 下面是业务逻辑
  }catch (err){
    await client.close(); // 关闭链接
    throw err
  }
}

上面的代码已经能很好的解决问题了,但是也有一个,如果需要关闭多种链接呢(比如RPC,DB,Socket等),一直try,catch也不是办法

受到Go的defer启发,于是写了这么一个库godefer , 依旧改写上面的代码

const godefer = require('godefer');

const main = godefer(async function(username, defer) {
  const client = await rpc.createConnection();

  // 注册一个defer函数
  defer(function() {
    client.close(); // 关闭链接
  });
  
  const data = await client.getUserInfo(username);
  
  // 下面是业务逻辑
  // ...
  // 运行完毕,则开始执行defer
});

Defer函数的执行,遵循了后进先出的原则, 即 先注册的defer函数,后运行

实现上与Go差不多, 有一点重要的差别是:

Go的defer内,能修改父级函数的返回值
godefer不能修改(不是不能做,而是不做)

好了,愉快的解决问题了, 有什么想法,评论来刚啊

@axetroy axetroy added the 学习 label Jan 10, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant