0%

JS 异步编程解决方案

首先是使用Promise。Promise是为了能更好的管理回调函数。

1
2
3
4
5
6
7
const func = (val) => {
return new Promise ((resolve, reject) => {
doSomething()
resolve(data)//成功
reject(data)//失败
})
}

这里的resolve和reject的data是返回给.then(data)中的data,意思就和return数据给下一个函数作为参数一样。完成链式调用。比如

1
2
3
4
5
6
func(val).then(dat => {
//这里的dat就是resolve来的data
}).catch(err => {
console.log(err)
})
//而reject的错误一般是用.catch()捕获然后再处理,也可以在catch里继续reject(err)给后面.catch(err)来处理。

不要在循环内部直接做异步操作,否则根本拿不到数据,循环就结束了
如果一定要做循环可以使用async.each或者使用Promise.all()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
async.each(record, (item, callback) => {
let result = {};
result.title = item.get('auction').get('title');
result.imgUrls = item.get('auction').get('imgUrls');
find(item.get('auction').get('objectId'))//把异步操作封装成一个Promise的方法对象
.then(userId => {
if (userId === item.get('userId')) {
result.status = 1;
} else {
result.status = 1;
}
result.heyzNum = item.get('heyzNum');
result.time = formatTime(item.get('createdAt'));
data.push(result);
callback();
}).catch(err => {
callback(err);
});
}, (err) => {
if (err) {
reject(err);
} else {
resolve(data);
}
})

使用Promise.all
但是如果这个promise队列里出现了reject,那么Promise.all()返回的结果会被一个reject而报销(其他正常返回也没用了)
Promise.all会把参数数组里的每个Promise的resolve都返回给下来then(results => {})中的results,会按顺序输出,以最后一个Promise完成为标志,进入then()
如果放在 Promise.all(promiseArr)中的 Promise 没有resolve, 那么 Promise.all 也无法运行
Promise例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const getActivitiesByCouponsAndModel = (activityModel) =>
new Promise((resolve, reject) => {
const newObj = Object.assign({}, activityModel);
const result = [];
for (let i = 0; i < activityModel.length; i++) {
result.push(mixCouponInfoById(activityModel[i].couponLists, newObj[i]));//mixCouponInfoById也是个返回Promise对象的方法,然后把Promise对象全部push到数组里。
}
return Promise.all(result)
.then(r => resolve({
success: true,
data: r
}))
.catch(e => reject({
error: 500,
message: e
}));
});

总的来说,async.each的逻辑更符合同步编程的逻辑,promise.all呢返回的是之前promises数组分别执行完的结果的数组,在后续的数据处理上可能比较麻烦