目录
- js异步处理方案,js的异步串行与异步并行
- 一、什么是串行,并行,并发
- 二、实现异步串行
- 三、实现异步并行
js异步处理方案,js的异步串行与异步并行
一、什么是串行,并行,并发
串行:这个就像队列一样,一个执行完,下一个再执行,比如js同步执行
并发:是指这个系统拥有处理多个任务的能力,在一定时间发出,不需要同时性执行。js的异步消息队列让js拥有并发的能力
比如执行多个settimeout 它会挂载在消息队列,然后依次执行
并行:是指这个系统拥同时处理多个任务的能力,属于多线程的一种方式,而js是属于单线程 虽然可以通过worker来创建多线程,但是子线程
完全受主线程控制,没有改变JavaScript单线程的本质
串行示意图:
有人会问,异步不是都在消息队列吗,不就是一个一个执行了吗?
举个例子,如果本身就是串行执行,那么你现在执行2给个任务,一个是5秒后打印console.log(1),一个是十秒后打印console.log(2)
按照串行应该是15秒执行完毕,但实际耗时是10秒,如上这是并发,
console.time()
setTimeout(() => {
console.log(1)
}, 5000);
setTimeout(() => {
console.log(2)
console.timeEnd()
}, 10000);
二、实现异步串行
大多时候我们可以用 promise 和async await来解决
promise
比较少的时候,可以用.then来实现串行
var a = function() {
return new Promise((resolve, reject) => {
setTimeout(() => {
consloe.log('a')
resolve('a')
}, 3000)
})
}
var b = function() {
return new Promise((resolve, reject) => {
setTimeout(() => {
consloe.log('b')
resolve('b')
}, 2000)
})
};
console.time('test')
a().then((aa) => {
b().then((bb) => {
console.log(`${aa}-${bb}`)
console.timeEnd('test')
})
})
async await
我们改造一下,明显使用await看起来更加清晰
var a = function() {
return new Promise((resolve, reject) => {
setTimeout(() => {
consloe.log('a')
resolve('a')
}, 3000)
})
}
var b = function() {
return new Promise((resolve, reject) => {
setTimeout(() => {
consloe.log('b')
resolve('b')
}, 2000)
})
};
(async () => {
console.time('test')
var aa = await a()
var bb = await b()
console.log(`${aa}-${bb}`)
console.timeEnd('test')
})()
但当我们有多个异步,比如2000个该如何
var createPromise = function(time) {
// then中的回调函数
return (resolve, reject) => {
return new Promise((resolve, reject) => {
setTimeout(() => { //模拟请求 (真实使用把time设置为0,将resolve传入异步函数中)
console.log('timein' + time)
resolve(); //在异步处理结束后resolve
}, time * 1000)
})
}
}
var arr = [createPromise(2), createPromise(3), createPromise(1), createPromise(4), createPromise(5)];
function serpromise(arr) {
arr.reduce((pre, next, index, carr) => {
return pre.then(next)
}, Promise.resolve())
}
// 相当于
// Promise.resolve().then(createPromise(2)).then(createPromise(1))......
serpromise(arr)
async await
var createPromise = function(time) {
return () => {
return new Promise((resolve, reject) => {
setTimeout(() => { //模拟请求 (真实使用把time设置为0,将resolve传入异步函数中)
console.log('timein' + time)
resolve(); //在异步处理结束后resolve
}, time * 1000)
})
}
}
var arr = [createPromise(2), createPromise(3), createPromise(1), createPromise(4), createPromise(5)];
var fn = async function(promiseArr) {
for (let i = 0, len = arr.length; i < len; i++) {
let currentPromise = promiseArr[i]
var result = await currentPromise()
}
}
fn(arr)
通过打印可以看出如过是并发的打印会是1,2,3,4,5
三、实现异步并行
并行示意图:
js并不能并行,我们只是可以思考如何卡在abc都执行完成,这里可以用promise.all 来轻松实现
const a = new Promise((resolve, reject) => {
//模拟异步任务
setTimeout(function() {
resolve('a');
}, 1000)
})
.then(result => result)
.catch(e => {
})
const b = new Promise((resolve, reject) => {
setTimeout(function() {
// resolve('b');
reject('Error in b');
}, 1000)
})
.then(result => result)
.catch(e => e)
Promise.all([a, b]).then(data => {
console.log('data', data)
})
.catch(e => console.log('erro', e));
这里需要注意的是,all能接受的 resolve reject都行,所以需要每个自己去处理异常
多个异步
promise
var createPromise = function(time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('time', time);
resolve(time)
}, time * 1000)
})
}
var arr = [createPromise(2), createPromise(3), createPromise(1), createPromise(4), createPromise(5)];
Promise.all(arr).then(data => {
console.log('data', data)
})
asnyc await
var createPromise = function(time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('time', time);
resolve(time)
}, time * 1000)
})
}
var arr = [createPromise(2), createPromise(3), createPromise(1), createPromise(4), createPromise(5)];
var fn = async function(promiseArr) {
let awaitArr = []
for (let i = 0, len = arr.length; i < len; i++) {
let currentPromise = promiseArr[i]
let result = await currentPromise
awaitArr.push(result)
}
return awaitArr
}
// async 返回的是一个promise
fn(arr).then(data => {
console.log('data', data);
})