dto 是只给前端需要的数据吗_后端直接向前端请求数据还是个新鲜事儿?

最近用 http://socket.io 写游戏的时候,发现怎么写怎么不爽。发送消息到不是什么事儿,但是接受消息就怎么用怎么不爽。试想一个场景,假设我向某个端请求一份数据,并且要求这个请求给我一份相应,而且一定要把这请求和响应一一对应,逻辑上不能打断。这直接用 http://socket.io 的 emit / on 的方式就感觉坑真多。前端向后端发送一份请求,并要求一份响应的时候还好,不是有 Ajax 嘛?后端向前端发送一份请求并要求一份响应呢?

于是,劳动人民就要发动劳动人民伟大的智慧,造了这么一个玩意儿 bramblex/io-request 。我给他取名叫做 IORequest,用来后端向前端请求一份数据并返回响应。嗯,请不要吐槽我取名字的能力。

IORequest 是如何设计的

IORequest 分为服务端和客户端两个部分,但是这两个部分都只监听并且发送,两个事件: io-request 和 io-response 。

流程大致是,A 端首先生成一个 message_id ,然后向 B 端发送 io-request 事件,并且附上 message_id,并且返回一个 promise。然后 B 端处理完各种东西以后向 A 端发送 io-resoponse 事件,同时附上从 io-request 上接受到的 message_id。最后,A 端接收到 io-response 事件,并通过 message_id 来 resolve 或者 reject 最先返回的 promise。【注】在这个过程中我唯一遇到的坑就是 Promise 这货不能在外部 resolve 或者 reject,而且在 node 里面还不能继承。所以只能通过一些 “奇技淫巧” ,通过外部的引用来把 resolve 和 reject 导出来,并给 promise 对象添加上。

如何使用

class Game {

constructor (left, right) {

co(function *() {

const home_id = next_home_id++

left.emit(`msg`, `游戏开始,游戏房间号[${home_id}],等待你出拳`)

right.emit(`msg`, `游戏开始,游戏房间号[${home_id}],等待你出拳`)

// 这里就是向前端请求 choice 方法,并且等待前端的返回 const [l, r] = yield [

left.ioRequest({method: 'choice'}),

right.ioRequest({method: 'choice'})

]

// 后端接受到前端的返回后继续游戏的进程 const _choices = [null, '布', '剪刀', '石头']

left.emit('msg', `你出的是[${_choices[l]}], 对方出的是[${_choices[r]}]`)

right.emit('msg', `你出的是[${_choices[r]}], 对方出的是[${_choices[l]}]`)

// 比较并且得出结果 if (Game.compare(l, r)) {

left.emit('msg', '你赢了')

right.emit('msg', '你输了')

} else {

right.emit('msg', '你赢了')

left.emit('msg', '你输了')

}

// 游戏结束,关闭链接 right.disconnect()

left.disconnect()

})

}

}

应为游戏逻辑都在后端处理了,那么前段就根本不需要再处理更多逻辑,而只需要负责处理后端的请求,并且显示后端推送的信息便可。

// 前端在这里只需要处理后端发送的 choice 请求,并且处理完后通过 response 返回请求的数据 ioReqClient.handle('choice', ({response}) => {

const choices = document.getElementById('choices')

choices.style.display = 'block'

const shi = document.getElementById('shi')

const jian = document.getElementById('jian')

const bu = document.getElementById('bu')

// 当按钮被点击的时候 shi.onclick = () => {

response(3) // 在这里给后端返回 choices.style.display = 'none'

msgLog('我出的是[石头]')

}

// 同上 jian.onclick = () => {

response(2)

choices.style.display = 'none'

msgLog('我出的是[剪刀]')

}

// 同上 bu.onclick = () => {

response(1)

choices.style.display = 'none'

msgLog('我出的是[布]')

}

})

最后放一张游戏的截图:

打开两个客户端会自动分配一个游戏房间:

当两个人都出了拳以后:

IORequest 解决了什么问题?

有些小伙伴问题,这个东西他到底有什么用呢?除了增加耦合以外?

嗯,当然是有用的啊,但是我这不叫做增加 “耦合” 而叫做 “聚合”。我们把不应该放在一起的事情放在一起做了,这就叫做耦合。但是我们把零零散散逻辑上本该一起做的东西放在一起了,这叫做聚合。所谓我们学习软件工程课程的时候常常听到一句话叫做 “高聚合,低耦合”。

IORequest 把零散的请求和相应整合到了一起,这就叫做聚合。而上面例子的 Game 类,把游戏运行逻辑和消息的发送放在了一起这叫做耦合。但是上面的 Game 类仅仅是一个非常简单的例子而已,只会用到一次,当然怎么方便怎么做嘛。

所以,IORequest 的作用,就是将 http://socket.io 的部分需要返回响应和他们做对应的请求整合在了一起而已,因为它们本就是逻辑上不可分割的一部分。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值