使用generator控制并发
推演如下:
第一版,分别取得请求的promise,等待第一个pr结束后,将结果存入data;再将第二个pr的结果存入data。
var data = []
function* gen (t, msg) {
data.push(yield req(t, msg))
}
let it1 = gen(100, 'req1')
let it2 = gen(100, 'req2')
let p1 = it1.next().value
let p2 = it2.next().value
// 排队处理请求
p1.then(res => {
it1.next(res) // 将请求的结果res返回给data
console.log(data) // 存入一个
return p2
}).then(res => {
it2.next(res)
console.log(data) // 存入两个
})
// 并发请求,但不是真正的并发器,这里无法控制请求数据,数据共享,结果处理等。
Promise.all([p1, p2]).then(res => {
console.log(res)
})
第二版 使用yield暂停来移交函数运行控制权,实现控制转移
var data = []
function* gen (t, msg) {
let res = yield req(t, msg)
yield // 暂停,移交控制权
data.push(res)
}
let it1 = gen(3000, 'req1')
let it2 = gen(300, 'req2')
let p1 = it1.next().value
let p2 = it2.next().value
p1.then(res => {
console.log('p1')
it1.next(res)
})
p2.then(res => {
console.log('p2')
it2.next(res)
})
Promise.all([p1, p2]).then(res => {
// 在此之前可以处理其他事件。
it1.next() // 恢复控制权。让外部有机会控制promise的结果什么时候返回。
it2.next()
console.log('res', res) // 直接返回结果。
console.log('data', data) // 没有恢复控制权data没有push,取不到结果为空。
})
第三版 加工
var data = []
function* gen (t, msg) {
let res = yield req(t, msg)
yield
data.push(yield res) // 将值传出后再入栈。
}
let it1 = gen(800, 'req1')
let it2 = gen(300, 'req2')
let p1 = it1.next().value
let p2 = it2.next().value
p1.then(res => {
console.log('p1')
it1.next(res)
})
p2.then(res => {
console.log('p2')
it2.next(res)
})
Promise.all([p1, p2]).then(res => {
let r1 = it1.next().value // 恢复控制权,并取得promise结果
let r2 = it2.next().value
r1 += '加工'
r2 += '加工'
it1.next(r1) // 加工promise结果后返回给生成器
it2.next(r2)
console.log('res after', res)
console.log('res data', data)
})
第四版 消息传递
实现数据共享
function* gen (data, t, msg) {
let params = yield { t, msg }
let res = yield req(params)
yield
data.push(yield res)
}
let globalData = []
let it1 = gen(globalData, 800, 'req1')
let it2 = gen(globalData, 300, 'req2')
let params1 = it1.next().value
let params2 = it2.next().value
// 外部根据需要,将生成器里面的数据取出并发送给其他生成器,实现生成器通讯。
let p1 = it1.next(params2).value // 交互参数
let p2 = it2.next(params1).value
p1.then(res => {
console.log('p1')
it1.next(res)
})
p2.then(res => {
console.log('p2')
it2.next(res)
})
Promise.all([p1, p2]).then(res => {
let r1 = it1.next().value
let r2 = it2.next().value
r1 += '=>r1:打印请求+写入日志'
r2 += '=>r2:打印请求+写入日志'
it1.next(r1)
it2.next(r2)
console.log('res after', res)
console.log('res globalData', globalData)
})
比如并发的时候,一旦有生成器处于空闲状态,就将数据传入处理。
而总的结果会在处理完成后返回(中间有日记记录或者其他操作),最后写入全局变量,进行全局处理。