0

私は単にこれを理解することはできません。ファイルを含むフォルダーがあります。これらのファイルの情報を含むjsonを作成したい。正確には、ファイル名、ファイル名の正規表現バージョン、および ajax 呼び出しから取得した追加データです。

個々のパーツは完璧に機能します。実際、コードを同期して実行すると、必要な結果が得られます。このようなもの:

 [
          { 
              "filename" : "first file",
              "regexname" : "first file",
              "ajaxresult" : "first file"
          },
          { 
              "filename" : "second file",
              "regexname" : "second file",
              "ajaxresult" : "second file"
          },
 ]

しかし、すべてを「同期」しようとすると、使用するXHRモジュールが正しく機能せず、特に多くのファイルでブロックされるため、非同期で実行したいと考えています。私の「同期」コードは次のようになります(短くするために少し簡略化されています)

  fs.readdir(datapath, function(err, files) { 
    var data = new Array();
        if(err) throw err;
        files.forEach(function(file){
            var filename = file
            , regex= filename.replace(/regex/)/i, "")
            , filepath = './public/config/dataconfig.js'
            , ajaxResults = getFile(url)
            , mapFiles = null

        mapFiles = { filename:filename, regexname:regex, ajaxcall:ajaxResults}
        data[data.length] = mapfiles;
    }
    var JSONdata= JSON.stringify(data, null, 4);
    fs.writeFile(filepath, JSONdata, function(e) {
        if (!e) {
            console.log('Done')
        }else{ 
            console.log('Failed', e)   
        };
    });
 });

ajaxcall を promise にラップしようとしましたが、promise 内のファイル名と正規表現名を失いました。そのようです:

  fs.readdir(datapath, function(err, files) { 
    var data = new Array();
        if(err) throw err;
        files.forEach(function(file){
            var filename = file
            , regex= filename.replace(/regex/)/i, "")
            , filepath = './public/config/dataconfig.js'
            , mapFiles = null

        // Make promise for async call with a url composed of the regex
        var promise = getFile(url);
        promise.then( function(result) {
             mapFiles = { filename:filename, regexname:regex, ajaxcall:result}
             data[data.length] = mapfiles;
                 var JSONdata= JSON.stringify(data, null, 4);
                 fs.writeFile(filepath, JSONdata, function(e) {
                    if (!e) {
                          console.log('Done')
                     }else{ 
                          console.log('Failed', e)   
                     };
                  });
            }); 
  });

これにより、次の結果が得られます。

 [
          { 
              "filename" : "first file",
              "regexname" : "first file",
              "ajaxresult" : "first file"
          },
          { 
              "filename" : "first file",
              "regexname" : "first file",
              "ajaxresult" : "second file"
          },
 ]

したがって、私の最終的な考えは、ノードに async モジュールのようなものを使用することでした。関数からコールバックを取得した後、json を記述します。しかし、私もそれを機能させることはできません。

前もって感謝します!

[編集 - 言い忘れたこと]

忘れていたのは、AjaxCall の URL が正規表現で作成されていることです。だから、このようなもの:

      url = 'http://www.test.com/'+regex

したがって、これは(私が見ているように)ajaxcallを呼び出す前に正規表現を実行することを意味しますが、呼び出し後にJsonに書き込むために正規表現も必要です。これが理にかなっていることを願っています

[編集 2 - もう少し情報]

私の XHR 呼び出しは次のようになります (誤った promise ソリューションはありません。その場合、promise を結果と共に返します):

// Get info
function getFile(url) { 
    xhr = new XMLHttpRequest(); 
    xhr.open("GET", url); 
    xhr.onreadystatechange = handler
    var ajaxResult = null
    //Callback
    function handler (){
        // If status is ready
        if (this.readyState == 4 && this.status == 200) {
            ajaxResult = eval(this.responseText);
            console.log('XHR OK')
        };
    };
    xhr.send(null);
    return ajaxResult[0];
};
4

3 に答える 3

1

正しく機能するpromiseに基づくソリューションは、次のようになります。

readdir(datapath).map(function (file) {
  return getFile(url)(function (ajaxresult) {
    return writeFile('./public/config/dataconfig.js', JSON.stringifiy({
      filename: file,
      regexname: file.replace(/regex/i, ""),
      ajaxcall: ajaxResult
    }, null, 4));
  });
}).end(function () {
  console.log("All done");
}, function (e) {
  console.log("Failed", e);
});

この例では、遅延promise実装を使用しました。これを機能させるには、すべての非同期関数がpromiseを返すことを確認する必要があります。一般的なコールバック関数は、deferred.promisifyを使用して簡単に変換できます。

var promisify = require('deferred').promisify;
var readdir = promisify(fs.readdir);
var writeFile = promisify(fs.writeFile);
于 2013-02-15T08:21:08.323 に答える
1

あなたが言及したように、asyncを使用した簡単な例を次に示します。

doStuffWithFiles('folder', 'output.json', function () {
  console.log('Done!');
});

function doStuffWithFiles (dirPath, outputFilePath, callback) {
  fs.readdir(dirPath, function (error, files) {
    async.map(
      files,
      function (file, callback) {
        doAjaxStuff(file, function (error, ajaxResults) {
          callback(null, {
            filename:    file,
            regexStuff:  file.replace(/stuff/, ''),
            ajaxResults: ajaxResults
          });
        });
      },
      function (error, results) {
        var data = JSON.stringify(results);
        fs.writeFile(outputFilePath, data, function (error) {
          callback();
        });
      }
    );
  });
}

重要な部分は、最初の関数に渡されたコールバックに引数として結果を返す必要があることを除いて、標準関数async.mapのように機能することです。すべてのコールバックが返されたら、2 番目の関数を呼び出して、結果のリストを渡します。mapasync.map

于 2013-02-14T20:46:02.343 に答える
0

問題がファイル名と正規表現を取得することである場合、それらを次のようにコールバックにバインドするのはどうですか

var callback = function(result) {
         mapFiles = { filename:this.filename, regexname:this.regex, ajaxcall:result}
         data[data.length] = mapfiles;
             var JSONdata= JSON.stringify(data, null, 4);
             fs.writeFile(filepath, JSONdata, function(e) {
                if (!e) {
                 console.log('Done')
                 }else{ 
                  console.log('Failed', e)   
                 };
              }

それから

promise.then(callback.bind({'filename':filename,'regex':regex}))
于 2013-02-14T20:38:31.743 に答える