如何使一些同步代码先于其他异步代码运行

How to make some synchronous code run before some other asynchronous code?

本文关键字:代码 其他 运行 异步 于其他 何使一 同步      更新时间:2023-09-26

我有一个这样的函数:

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

两个部分将同时运行

不,他们不会。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代替。

您正在使用同步函数,因此调用被阻塞。然而,正如四眼所提到的,出于性能原因,最好使用异步版本。

如果你想避免回调地狱(即你的代码变得越来越难以阅读,因为你链异步调用),你可以使用一个库,如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,纤维。js为例)