基本使用
下面是 async
与 Promise
异步操作的基本使用。
使用场景:当异步操作需要按顺序执行时可以使用,如按顺序读取多个文件内容。
限制:await
后面表达式 异步出错了 会中断下一步的await
表达式的异步执行;
let asyncFn = async function() {
await Promise.resolve('hello world 1').then(v => {
console.log(v);
});
await Promise.resolve('hello world 2').then(v => {
console.log(v);
});
await Promise.resolve('hello world 3').then(v => {
console.log(v);
});
}
asyncFn(); //hello world 1 hello world 2 hello world 3
出错例子
let asyncFn = async function() {
await Promise.reject('出错了');
await Promise.resolve('hello world').then(v => {
console.log(v);
});
}
asyncFn();
但是,如果使用了catch
捕获错误,后面的异步可以继续执行;
let asyncFn = async function() {
await Promise.reject('出错了').catch(e => {
console.log(e);
});
await Promise.resolve('hello world').then(v => {
console.log(v);
});
}
asyncFn(); //出错了 hello world
如果需要捕获错误,对错误进行处理的同时中断下一步异步的执行,需要用到try...catch
await
放在 try...catch
里面,try...catch
捕获错误,Promise
不要使用catch
先行捕获
let asyncFn = async function() {
try {
await Promise.reject('出错了 1');
await Promise.resolve('hello world').then(v => {
console.log(v);
});
await Promise.reject('出错了 2');
} catch (e) {
console.log(e);
}
}
asyncFn(); //出错了 1
当 使用场景是多个异步访问时,异步出错不中断下个await
执行,如:批量导入数据;
下面是 续发:一个异步执行完毕之后再执行下一个异步的 执行’方式。这样做比较耗时,但可以防止高并发,防止线程阻塞,减少服务器压力;
try...catch
统一处理异步出错;
let asyncFn = async function() {
for (var i = 0; i < 5; i++) {
try {
await Promise.reject('出错了');
} catch (e) {
console.log(e);
}
}
await Promise.resolve('hello world').then(v => {
console.log(v);
});
}
asyncFn(); //出错了 出错了 出错了 出错了 出错了 hello world
Promise...catch
按需处理异步出错
let asyncFn = async function() {
for (var i = 0; i < 5; i++) {
await Promise.reject('出错了').catch(e => {
console.log(e);
});
}
await Promise.resolve('hello world').then(v => {
console.log(v);
});
}
asyncFn(); //出错了 出错了 出错了 出错了 出错了 hello world
当我们需要 同时触发:同时执行过个异步操作。服务器压力不大时,这样可以节省时间。
let nowDate1, nowDate2;
let asyncFn = async function() {
await Promise.all([Promise1(), Promise2()])
console.log('nowDate1-nowDate2', nowDate1 - nowDate2);
}
function Promise1() {
return new Promise(function(resolve, reject) {
setTimeout(() => {
resolve();
}, 3000);
}).then(() => {
nowDate1 = Date.parse(new Date())
console.log('nowDate1', nowDate1);
})
}
function Promise2() {
return new Promise(function(resolve, reject) {
setTimeout(() => {
resolve();
}, 1000);
}).then(() => {
nowDate2 = Date.parse(new Date())
console.log('nowDate2', nowDate2);
})
}
asyncFn();
//nowDate2 1608263144000
//nowDate1 1608263146000
//nowDate1-nowDate2 2000
从上面可以看出 两个异步的时间差是2000毫秒,而不是1000毫秒,说明两个异步是同时执行的;
Promise.all
可以时同时触发异步请求;
或者上例子的
await Promise.all([Promise1(), Promise2()])
改为
let fooPromise = Promise1();
let barPromise = Promise2();
let foo = await fooPromise;
let bar = await barPromise;
这样也会同时触发异步请求;
下面是一个 异步批量导入demo
// 防止高并发 一个请求完成后再执行下一个请求
const request = require('request');
let asyncFn = async function() {
for (var i = 0; i < changeList.length; i++) {
await putCompany(changeList[i], i);
}
}
asyncFn();
function putCompany(item) {
return new Promise(function(resolve, reject) {
let requestData = {
}
request({
url: URL + '/api/company',
method: "PUT",
json: true,
headers: {
"content-type": "application/json",
'Authorization': Token,
},
body: item
},
function(err, response, body) {
if (!err && (response.statusCode == 200 || response.statusCode == 204)) {
resolve(body);
} else {
reject(err);
}
})
}).then((res) => {
if (res && res.content && res.content.length) {
companyList = res.content;
}
console.log('putCompany res 修改成功!', res);
}).catch((error) => {
console.error('putCompany error ', index, error);
errorList.push(item);
});
};