Open
Description
- 实际项目中遇到的串行并行控制问题
- 如何使用async,await实现串行控制
- 如何使用promise.all实现并行控制
- 如何使用第三方库Nimble实现串并行控制
- 如何使用第三方库blueBird实现串并行控制
实际项目中遇到的串行并行控制问题
最近也遇到了一个并发请求导致服务端插入重复数据报错的坑,是因为前端并发了多个相同的Create请求,服务端多线程提交数据库事务存在冲突,所以导致报错。但是由于前端发送重复请求是相对较好的处理方式,所以最终改成了阻塞请求。
具体的前端实现方式,异步并发:Promise.all;同步阻塞:await。Promise.all异步并发与await同步阻塞。
并发式的Promise.all(导致后端服务出问题)
async promiseAllAsyncConcurrence(items) {
const promiseArr = [];
for (let i = 0; i < 9; i++) {
promiseArr[i] = new Promise((resolve)=>{
setTimeout(()=>{
resolve(items[i]);
}, Math.random()*1000)
})
}
return Promise.all(promiseArr);
}
const sourceArr = ['foo', 'bar', 'baz']
const resultArr = await promiseAllAsyncConcurrence(sourceArr);
阻塞式的await(后端服务正常运转)
awaitSequenceSync(item) {
return new Promise((resolve)=>{
setTimeout(()=>{
resolve(items);
}, Math.random()*1000)
})
}
const sourceArr = ['foo', 'bar', 'baz']
const resultArr = [];
for (let i = 0; i < 9; i++) {
// eslint-disable-next-line
resultArr[i] = await awaitSequenceSync(sourceArr[i]);
}
注意:如果不添加会报ESLint error: Unexpected await inside a loop no-await-in-loop
并发的Promise.all添加setTimeout定时器(不推荐)
async promiseAllAsyncConcurrence(items) {
const promiseArr = [];
for (let i = 0; i < 9; i++) {
promiseArr[i] = new Promise((resolve)=>{
setTimeout(()=>{
new Promise((resolve)=>{
setTimeout(()=>{
resolve(items[i]);
}, Math.random()*1000)
})
}, (i+1)*500) // 每个请求间隔500ms
})
}
return Promise.all(promiseArr);
}
const sourceArr = ['foo', 'bar', 'baz']
const resultArr = await promiseAllAsyncConcurrence(sourceArr);
如何使用async,await实现串控制
/**
* 串行控制:一个接着一个发请求
* @param {*} items
* @param {*} asyncFunc
*/
function seriesFlow(items, asyncFunc) {
const result = [];
items.forEach(async (item, i) => {
result[i] = await asyncFunc(item);
});
return result;
}
如何使用promise.all实现并行控制
/**
* 并行控制:请求一次性并行发出
* @param {*} items
* @param {*} asyncFunc
*/
function parallelFlow(items, asyncFunc) {
return new Promise((resolve, reject) => {
const promises = [];
items.forEach((item, i) => {
promises[i] = asyncFunc(item);
});
return Promise.all(promises)
.then(data => {
resolve(data);
})
.catch(err => {
reject(err);
});
});
}
使用示例可以到我的个人npm ujf查看:https://www.npmjs.com/package/ujf
上面源码位置:https://github.com/FrankKai/UJF/blob/master/src/task.js
如何使用第三方库Nimble实现串并行控制
Nimble串行控制
Series会在之前的一个函数完成后再执行下一个函数,最后一个函数执行完毕时进入最终回调。
_.series([
function (callback) {
setTimeout(function () {
console.log('one');
callback();
}, 25);
},
function (callback) {
setTimeout(function () {
console.log('two');
callback();
}, 0);
}
], ()=>{
// do something...
});
Nimble并行控制
Parallel会同时执行所有函数,当所有函数执行完毕时进入最终回调。
_.parallel([
function (callback) {
setTimeout(function () {
console.log('one');
callback();
}, 25);
},
function (callback) {
setTimeout(function () {
console.log('two');
callback();
}, 0);
}
], ()=>{
// do something...
});
参考资料http://caolan.github.io/nimble/
如何使用第三方库blueBird实现串并行控制
Promise.mapSeries实现串行控制
参考资料:http://bluebirdjs.com/docs/api/promise.mapseries.html