https://segmentfault.com/q/1010000005943986?_ea=966070
上次我问过一个问题, 这个问题解答了一步一步通过promise异步后再完成的方法,但今天我突然又想到另一种情况,如果有好几个异步操作可以同时进行,但必须等它们全部完成后才能进行下面的操作,应该如何编码呢?设想下面的情况:
我们需要读几个文件,它们没有必然的先后关系,只要都读完就可以,但必须都读完才能进行下一步,请问该怎么做呢?
https://segmentfault.com/q/1010000005943986?_ea=966070
上次我问过一个问题, 这个问题解答了一步一步通过promise异步后再完成的方法,但今天我突然又想到另一种情况,如果有好几个异步操作可以同时进行,但必须等它们全部完成后才能进行下面的操作,应该如何编码呢?设想下面的情况:
我们需要读几个文件,它们没有必然的先后关系,只要都读完就可以,但必须都读完才能进行下一步,请问该怎么做呢?
var getFile = function(filename) {
return new Promise(function(resolve, reject){
//读取文件
resolve(filename + '中的文件内容');
});
}
Promise.all([getFile('文件1'),getFile('文件2'),getFile('文件3')])
.then(function(res){
//res:['文件1的内容','文件2的内容','文件3的内容']
})
用async
async.parallel({
swslist: function(callback){
var param = {
v_act: 'v_swslist',
v_ldata: 'btype:0',
v_lnum: 10,
v_lpage: 1,
v_mid: settings.Interface.mid
};
functions.dz_http_get(param, function(data){
callback && callback(null, data)
});
},
webIlist: function(callback){
var param = {
v_act: 'v_webIlist',
v_id: 5,
v_mid: settings.Interface.mid,
v_type: 2
};
functions.dz_http_get(param, function(data){
callback && callback(null, data)
});
}
}, function(err, results){
if(err || typeof results.swslist === 'string' || typeof results.webIlist === 'string'){
res.render('error.html', {
errormsg: msg.parameter_error
});
return;
}
res.render('business/index.html', {
busList: results.swslist,
articleList: results.webIlist,
label_css: 'dz_label_swbc',
label: msg.pagename.business
});
});
用bluebird
的Promise。Promise.all
可以用来处理一组Promises,也可以用Promise.join
,可以用来处理几个Promises的情况。
文档看这里。
var fs = require('fs');
var completedTasks = 0;
var tasks = [];
var filesDir = './text';
function checkIfComplete(){
completedTasks++;
if(completedTasks == tasks.length){ //读取文件任务完成
}
}
fs.readdir(filesDir, function(err, files){
if(err) throw err;
for(var index in files ){
var task = (function(file){
return function(){
fs.readFile(file, function(err, text){
if(err) throw err;
checkIfComplete();
})
}
})(filesDir + '/'+ files[index]);
tasks.push(task);
}
for(var task in tasks ){
tasks[task]();
}
})
今天我也遇到了这个问题,看到了 无才狂士 推荐的地址去学习后,完成了自己的需求:
router.post('/', function(req, res, next) {
var form = new multiparty.Form();
form.uploadDir = tmpDir;
form.parse(req, function(err, fields, files) {
// console.log(util.inspect(fields, true));
// console.log(util.inspect(files, true));
///将移除,移动文件封装成 promise.
function rename(f){
return new Promise(function(resolve,reject){
if(f.size > 0){
const fName = f.originalFilename;
const newPath = uploadDir + fName;
///目标文件已经存在的话会被覆盖!
fs.rename(f.path,newPath,function(err){
if(err){
reject(err);
console.log('save file:' + newPath + ';err:' + err.toString());
}else{
console.log('save file:' + newPath);
resolve(fName);
}
});
}else{
fs.unlink(f.path,function(err){
if(err){
reject(err);
console.log('delete empty file:' + f.path + ';err:' + err.toString());
}else{
console.log('delete empty file:' + f.path);
resolve('');
}
});
}
});
}
///处理参数值,拿到的值包裹在数组里了,给去掉;
Object.keys(fields).forEach(function(name) {
const arr = fields[name];
value = arr.length > 0 ? arr[0] : '';
fields[name] = value;
});
///处理文件,所有文件都放在一起;
const fileList = [];
Object.keys(files).forEach(function(name) {
const arr = files[name];
arr.forEach(function(v){
fileList.push(v);
});
});
///将文件数组映射为promise任务;
const tasks = fileList.map(function(v){
return rename(v);
});
///任务全部完成后,给客户端响应;
Promise.all(tasks).then(function(value){
console.log('all:' + value.toString());
// public/upload/Icon-24@2x.png,public/upload/Icon-29@3x.png,public/upload/Icon-40.png
///处理文件名,字符串转成数组,去掉空串,空串意味着客户端表单里没文件
const fileNameArr = value.toString().split(',');
for(var i = fileNameArr.length-1; i >= 0 ; i --){
const e = fileNameArr[i];
if(e.length == 0){
fileNameArr.splice(i,1);
}
}
///构建响应结构体
const result = {};
result['status'] = 200;
result['msg'] = 'received ' + fileNameArr.length + ' files!';
result['ps'] = fields;
result['files'] = fileNameArr;
res.json(result);
// res.writeHead(200, {'content-type': 'application/json'});
// res.write(JSON.stringify(result));
// res.end();
}).catch(function(err){
///构建异常结构体
const result = {};
result['status'] = 5000;
result['msg'] = err.toString();
res.json(result);
});
});
});
完整代码:https://github.com/debugly/SCNetworkKit/blob/master/Server/routes/upload.js
10 回答10.3k 阅读
4 回答8.6k 阅读✓ 已解决
7 回答10.7k 阅读
2 回答11.2k 阅读✓ 已解决
6 回答2.4k 阅读
5 回答4.2k 阅读✓ 已解决
4 回答2.5k 阅读✓ 已解决
可以用 Promise.all。
具体用法可以参考:链接描述