如何在其他一些异步代码之前制作一些同步代码 运行?
How to make some synchronous code run before some other asynchronous code?
我有这样的函数:
var download = function(url, name) {
http.get(url, function(response) {
// part1 : create a new folder if it doesn't exist
dir = './name';
if (!fs.existsSync(dir)){
fs.mkdirSync(dir);
}
// part 2: download and save file into that folder
response.on('data', function (data) {
fs.appendFileSync(dir, data);
});
})
}
我希望第 1 部分在第 2 部分 运行 之前完成(这样我就可以获得第 2 部分的目录)。我怎样才能做到这一点 ?
(在上面的代码中,据我所知(我是 node.js 的新手),两个部分将同时 运行,所以我不确定第 1 部分是否总是会完成在第 2 部分之前 运行s).
both parts will run simultaneously
不,他们不会。 existsSync
和 mkdirSync
是阻塞调用。因此,只有在它们执行后,事件处理程序才会被附加。
但是,我们应该在适用的时候利用异步性。在这种情况下,您可以使用 exists
和 mkdir
异步对应项。
因此,您的代码可以像这样松散地重构
function download(url, name) {
function attachAppender(filename, response) {
response.on('data', function (data) {
fs.appendFile(filename, function (err) {
res.statusCode = err ? 500 : 200;
response.end();
});
});
}
http.get(url, function (response) {
var dir = './name';
fs.exists(dir, function (exists) {
if (!exists) {
fs.mkdir(dir, function (err) {
if (err) {
res.statusCode = 500;
res.end();
} else {
// pass the actual full file name
attachAppender(filename, response);
}
});
} else {
attachAppender(filename, response);
}
});
});
}
注意: fs.exists
已弃用,可能很快就会被删除。最好使用 fs.stat
而不是它。
您正在使用同步功能,因此调用被阻塞。但是,正如 thefoureye 提到的那样,出于性能原因,最好使用异步版本。
如果你想避免写callback hell (i.e your code becomes more and more difficult to read as you chain asynchronous calls), you can use a library such as async.js 的意图是试图让它更容易写(当然也更容易阅读)。
这里是取自 async.js 的单元测试的示例:每个异步函数都在另一个之后调用。
var series = function(test){
var call_order = [];
async.series([
function(callback){
setTimeout(function(){
call_order.push(1);
callback(null, 1);
}, 25);
},
function(callback){
setTimeout(function(){
call_order.push(2);
callback(null, 2);
}, 50);
},
function(callback){
setTimeout(function(){
call_order.push(3);
callback(null, 3,3);
}, 15);
}
],
function(err, results){
test.ok(err === null, err + " passed instead of 'null'");
test.same(results, [1,2,[3,3]]);
test.same(call_order, [1,2,3]);
test.done();
});
}
为了使一系列异步调用更易于读写,还有许多其他举措(例如async/await、fibers.js)
我有这样的函数:
var download = function(url, name) {
http.get(url, function(response) {
// part1 : create a new folder if it doesn't exist
dir = './name';
if (!fs.existsSync(dir)){
fs.mkdirSync(dir);
}
// part 2: download and save file into that folder
response.on('data', function (data) {
fs.appendFileSync(dir, data);
});
})
}
我希望第 1 部分在第 2 部分 运行 之前完成(这样我就可以获得第 2 部分的目录)。我怎样才能做到这一点 ?
(在上面的代码中,据我所知(我是 node.js 的新手),两个部分将同时 运行,所以我不确定第 1 部分是否总是会完成在第 2 部分之前 运行s).
both parts will run simultaneously
不,他们不会。 existsSync
和 mkdirSync
是阻塞调用。因此,只有在它们执行后,事件处理程序才会被附加。
但是,我们应该在适用的时候利用异步性。在这种情况下,您可以使用 exists
和 mkdir
异步对应项。
因此,您的代码可以像这样松散地重构
function download(url, name) {
function attachAppender(filename, response) {
response.on('data', function (data) {
fs.appendFile(filename, function (err) {
res.statusCode = err ? 500 : 200;
response.end();
});
});
}
http.get(url, function (response) {
var dir = './name';
fs.exists(dir, function (exists) {
if (!exists) {
fs.mkdir(dir, function (err) {
if (err) {
res.statusCode = 500;
res.end();
} else {
// pass the actual full file name
attachAppender(filename, response);
}
});
} else {
attachAppender(filename, response);
}
});
});
}
注意: fs.exists
已弃用,可能很快就会被删除。最好使用 fs.stat
而不是它。
您正在使用同步功能,因此调用被阻塞。但是,正如 thefoureye 提到的那样,出于性能原因,最好使用异步版本。
如果你想避免写callback hell (i.e your code becomes more and more difficult to read as you chain asynchronous calls), you can use a library such as async.js 的意图是试图让它更容易写(当然也更容易阅读)。
这里是取自 async.js 的单元测试的示例:每个异步函数都在另一个之后调用。
var series = function(test){
var call_order = [];
async.series([
function(callback){
setTimeout(function(){
call_order.push(1);
callback(null, 1);
}, 25);
},
function(callback){
setTimeout(function(){
call_order.push(2);
callback(null, 2);
}, 50);
},
function(callback){
setTimeout(function(){
call_order.push(3);
callback(null, 3,3);
}, 15);
}
],
function(err, results){
test.ok(err === null, err + " passed instead of 'null'");
test.same(results, [1,2,[3,3]]);
test.same(call_order, [1,2,3]);
test.done();
});
}
为了使一系列异步调用更易于读写,还有许多其他举措(例如async/await、fibers.js)