2015-08-01 2 views
1

У меня есть функция, как это:Как сделать некоторый синхронный запуск кода перед другим асинхронным кодом?

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).

+0

* обе части будут работать одновременно * - Нет, они не будут. 'existsSync' и' mkdirSync' блокируют вызовы. Таким образом, только после того, как они будут выполнены, обработчик события будет прикреплен. – thefourtheye

+0

В Node.js, если вы видите метод, заканчивающийся на 'Sync', это означает, что он будет работать синхронно. (Подобно простому C/Java/C# и т. Д.). Вы не используете эти методы в Node.js, так как в основном это связано с асинхронным исполнением. – Xeon

+0

@ thefourtheye: thks для вашего объяснения –

ответ

1

обе части будут работать одновременно

Нет, они не будут. 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 вместо него.

0

Вы используете функции синхронизации, чтобы блокировать вызовы. Однако, как упомянуто выше, лучше использовать асинхронные версии по соображениям производительности.

Если вы хотите избежать callback hell (т. Е. Ваш код становится все труднее читать, поскольку вы связываете асинхронные вызовы), вы можете использовать библиотеку, такую ​​как 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(); 
    }); 
} 

Есть много других инициатив, с тем чтобы сделать серию асинхронных вызовов легче читать и писать (асинхронное/ОЖИДАНИЕ, fibers.js, например)

Смежные вопросы