Как использовать обратный вызов или Async в течение цикла? - PullRequest
0 голосов
/ 20 ноября 2018

Я ищу и читаю об асинхронных функциях и обратных вызовах.Но я не смог решить свою проблему в течение недели.Я хочу сделать 'fs readfile' внутри цикла с порядком.Я пытаюсь сделать следующее, но у меня ничего не получается.

// on the code below, console.log print the value in random order and 'storedata' is empity.
// my goal is to do readfile in loop orderly and store the value

router.get("/files/readfiles", function(req,res){
  var storedata= []; 
  var filenames= ["file1","file2","file3","file4"]; 

  for (var i=0; i< filenames.length; i++){      
    fs.readFile('views/allfiles/'+ filenames[i] +'.ejs','utf8',function (err, data) {
      if (err) throw err;  
      storedata.push(data);         
      console.log(data);         
    });
    console.log(storedata); // this returns empty array
  });

Я также пытаюсь по-другому:

router.get("/files/readfiles", function(req,res){
var filenames= ["file1","file2","file3","file4"];   

filenames.forEach(readfiles);

function readfiles(value) {
  var dataread =  fs.readFile('views/allfiles/'+ value +'.ejs','utf8')

    console.log (dataread);
   }
});

на вышеупомянутой попытке я получаю ошибку: TypeError [ERR_INVALID_CALLBACK]:Обратный вызов должен быть функцией.

Я новичок в асинхронных методах, любая помощь, пожалуйста.

Ответы [ 3 ]

0 голосов
/ 20 ноября 2018

Ваш второй код не обеспечивает функцию обратного вызова, это ваша ошибка.

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

Это будет выглядеть так:

router.get("/files/readfiles", function(req,res){
  var storedata= []; 
  var filenames= ["file1","file2","file3","file4"]; 

  for (let i = 0; i< filenames.length; i++){      
    fs.readFile('views/allfiles/'+ filenames[i] +'.ejs','utf8',function (err, data) {
      if (err) throw err;  
      storedata[i] = data;

      if (storedata.length === filenames.length) {
        console.log(storedata);
        // do stuff you want, like:
        res.send(storedata)
      }            
     });
  });

Если вы планируете использовать узел 10, я рекомендую вам посмотреть другой ответ с Promise.all.Асинхронное ожидание велико

0 голосов
/ 06 декабря 2018

Вы должны использовать синтаксис ES2017 async/await следующим образом.

router.get("/files/readfiles", async function(req, res){
  var storedata= []; 
  var filenames= ["file1","file2","file3","file4"]; 

  for (var i=0; i< filenames.length; i++){  
    await new Promise((resolve, reject) => {    
        fs.readFile('views/allfiles/'+ filenames[i] +'.ejs','utf8',function (err, data) {
          if (err) return reject( err )
          storedata.push(data);
          resolve();               
        });
    })
    console.log(storedata);
  }
});
0 голосов
/ 20 ноября 2018

Если вы используете Node v10 или выше, вы можете использовать fs обещания API и async / await.

Для чтения файлов последовательно:

router.get( "/files/readfiles", async function( req, res ) {
  const storedata = [ ]; 
  const filenames = [ "file1", "file2" , "file3", "file4" ]; 

  for (let i = 0; i < filenames.length; i++ ) {      
    const data = await fs.promises.readFile( 'views/allfiles/'+ filenames[i] +'.ejs', { encoding: 'utf8' } ); 
    storedata.push( data );         
  }

  console.log( storedata ); 

} );

или читать их параллельно:

router.get( "/files/readfiles", async function( req, res ) {
  const promises = [ ]; 
  const filenames = [ "file1", "file2", "file3", "file4" ]; 

  for (let i = 0; i < filenames.length; i++ ) {      
    const promise = fs.promises.readFile( 'views/allfiles/'+ filenames[i] +'.ejs', { encoding: 'utf8' } ); 
    promises.push( promise );         
  }

  const storedata = await Promise.all( promises );

  console.log( storedata ); 

} );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...