需求
有一个 HTTP 接口 A,后端会执行一段异步任务 发一个 HTTP 请求到 B 站点,B 站点异步执行后 callback A 站点的 HTTP 接口。
我想客户端请求的时候阻塞一下 A <—> B 这个过程,让客户端使用 A 的时候基本无感,有没有什么比较好的处理方案?
现有方案
标记每一个请求,A 接口上轮询等待 B 接口的返回结果。有其他更好的事件流或者闭包处理方案吗? 伪代码
const POOL = {}
function sleep(timer = 100) {
return new Promise(resolve => {
setTimeout(resolve, timer)
})
}
// 客户端请求的接口
async function handle(ctx) {
const tid = Math.random().toString()
await axios.post('xxx', { tid })
POOL[tid] = null
for (let i = 0; i <= 100; i++) {
// 轮询 POOL 有没有返回值
if (POOL[tid]) {
break
}
await sleep()
}
const res = POOL[tid]
if (!res) {
ctx.throw(500)
}
ctx.body = res
}
async function callback() {
const { tid, payload } = ctx.request.body
if (POOL[tid] !== undefined) {
POOL[tid] = payload
}
ctx.body = 'ok'
}
上websocket 完成后通知浏览器
@xcstream 需求是异步转同步,就相当于这一部分异步操作想要阻塞成类似sql的慢查询
上个消息队列或者redis的订阅发布机制不就行了吗。
没明白的是: 客户端使用 A 的时候基本无感 ? 异步 同步 一样需要有个等待过程的啊 (网络/IO 都是需要时间的)。
如果你是解决 轮询问题,那 weboscket 或者 http2 的push 功能可以解决。
如果这个等待时间比较短,频次也比较低,那一直让这个连接保持就行了,等有数据再返回。
@guojingkang 订阅等待的过程中怎么阻塞 A 端这个 HTTP 请求
@wiviwiv 你的需求不太清晰呀,最好能清晰得描述下流程
@guojingkang 使用 A 服务请求 B 服务的资源,期间阻塞 A 上面的请求 直到 B 返回结果 B 服务是一个异步任务,请求完成后通过回调通知 A 的请求是否完成。
@wiviwiv A 向 B发起请求,B进行处理,建议这里用一个中间结构来处理 B 返回结果,sql或者redis等等等,A 主动轮询中间结构,得到想要的结果再 res.end