如何在某些其他异步代码之前运行某些同步代码?

时间:2015-08-01 09:16:09

标签: javascript node.js asynchronous nonblocking synchronous

我有这样的功能:

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部分运行之前完成)。

2 个答案:

答案 0 :(得分:1)

  

两个部分将同时运行

不,他们不会。 existsSyncmkdirSync阻止了来电。因此,只有在执行它们之后才会附加事件处理程序。

但是,我们应该在适用的时候利用异步性。在这种情况下,您可以使用existsmkdir异步对应项。

所以,你的代码可以像这样松散地重构

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代替它。

答案 1 :(得分:0)

您正在使用同步功能,因此呼叫会被阻止。但是,正如thefoureye所提到的,出于性能原因,最好使用异步版本。

如果你想避免使用callback hell(即在链接异步调用时你的代码变得越来越难以阅读),你可以使用写在意图中的async.js等库。试图让它更容易编写(当然,更容易阅读)。

以下是从async.js的单元测试中获取的示例:每个async函数都是在另一个之后调用的。

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),还有很多其他举措