2017-11-21 8 views
-1

私はアーカイブから指定されたファイルを抽出し、コールバックであり、コンテンツを与えることができ、コードを持っているすべての最初の、だから... ...何でも、いくつかのMinecraftのもののためのユーティリティを書いている:[0]を追加すると、コールバックが2回呼び出されますか?

const unzip = require("unzip-stream"); 
const Volume = require("memfs").Volume; 
const mfs = new Volume(); 
const fs = require("fs"); 

function getFile(archive, path, cb) { 
    let called = false; 

    fs.createReadStream(archive) 
     .pipe(unzip.Parse()) 
     .on("entry", function(entity) { 
      if (path.includes(entity.path)) { 
       entity.pipe(mfs.createWriteStream("/" + path)) 
        .on("close", function() { 
         mfs.readFile("/" + path, function(err, content) { 
          if (!called) cb(content); 
          called = true; 
          mfs.reset(); 
         }); 
        }).on("err",() => {}); 
      } else { 
       entity.autodrain(); 
      } 
     }); 
} 

module.exports = { getFile }; 

たときにこれは完璧な作品私は対話コンソールでそれをテストする:

require("./zip").getFile("minecraft-mod.jar", ["mcmod.info", "cccmod.info"], console.log); // <= Works fine! Calls callback ONCE! 

このコードを使ってユーティリティを開発し始めたとき、私は非常に奇妙なことを発見しました。

だから私はfilesのファイル名を持っています。

私はasync/eachSeriesを繰り返し使用しています。私はコールバック機能を持っていない - 1つだけを繰り返します。

私は改造中のファイルを.json解析するには、このコードを持っている:

let modinfo = Object.create(JSON.parse(content.replace(/(\r\n|\n|\r)/gm,""))); 

また、正常に動作します。しかし、ここで魔法が来る...

したがって、.jsonファイルは配列またはオブジェクトを含むことができます。それは配列なら我々はそれの最初の要素を取る必要があります。

if (modinfo[0]) modinfo = modinfo[0]; 

それは動作します。

しかし、我々は中にmodlistプロパティの最初の要素を取る必要があり、それのオブジェクトの場合:

else modinfo = modinfo.modlist[0]; 

とのmodinfoだったとオブジェクトブーム場合 - コールバックは今TWICE発射!何?私は他の状態から[0]削除する場合

しかし、:

else modinfo = moninfo.modlist; // <= No [0] 

コールバックはONCEと呼ばれます! ???

私はこのような何かをしようとした場合

if (modinfo[0]) modinfo = modinfo[0]; 
else { 
    const x = modinfo.modlist; 
    modinfo = x[0]; 
} 

同じことが起こる...

また、それは、引数なしで呼ばれています。

私は、コールバックが2回呼び出される場所を調査しようとしました。 zip抽出プログラムのコードをもう一度読む...

let called = false; 

そして、それら:

この

:それはそれらの行を持っている

if (!called) cb(content); 
called = true; 

だから、もしアップ何らかの理由であっても、この条件火災2回:

if (path.includes(entity.path)) { 

それをコールバックを呼び出すべきではありません。いいえ!それだけでなく、試してみると

console.log(called); 

これはfalseに2回記録されます!

NodeJSバージョン:V8.0.0

全コード:

function startSignCheck() { 
 
    clear(); 
 

 
    const files = fs.readdirSync("../mods"); 
 

 
    async.eachSeries(files, function(file, cb) { 
 
    console.log("[>]", file); 
 

 
    zip.getFile("../mods/" + file, ["mcmod.info", "cccmod.info"], function(content) { 
 
     console.log(content); 
 
     console.log(Buffer.isBuffer(content)); 
 

 
     if (content != undefined) content = content.toString(); 
 

 
     if (!content) return cb(); 
 

 
     let modinfo = Object.create(JSON.parse(content.replace(/(\r\n|\n|\r)/gm, ""))); 
 

 
     if (modinfo[0]) modinfo = modinfo[0]; 
 
     else modinfo = modinfo.modlist[0]; 
 

 
     //if (!modinfo.name) return cb(); 
 

 
     /*curse.searchMod(modinfo.name, modinfo.version, curse.versions[modinfo.mcversion], function(link) { 
 
     \t if (!link) return cb(); 
 

 
     \t signature.generateMD5("../mods/" + file, function(localSignature) { 
 
     \t \t signature.URLgenerateMD5(link, function(curseSignature) { 
 
     \t \t \t if (localSignature === curseSignature) { 
 
     \t \t \t \t console.log(file, "- Подпись верна".green); 
 
     \t \t \t } else { 
 
     \t \t \t \t console.log(file.bgWhite.red + " - Подпись неверна".bgWhite.red); 
 
     \t \t \t } 
 

 
     \t \t \t cb(); 
 
     \t \t }); 
 
     \t }); 
 
     });*/ 
 
    }); 
 
    }); 
 
}

mcmod.infoの例の内容は次のとおりです。

{ 
    "modListVersion": 2, 
    "modList": [{ 
    "modid": "journeymap", 
    "name": "JourneyMap", 
    "description": "JourneyMap Unlimited Edition: Real-time map in-game or in a web browser as you explore.", 
    "version": "1.7.10-5.1.4p2", 
    "mcversion": "1.7.10", 
    "url": "http://journeymap.info", 
    "updateUrl": "", 
    "authorList": ["techbrew", "mysticdrew"], 
    "logoFile": "assets/journeymap/web/img/ico/journeymap144.png", 
    "screenshots": [], 
    "dependants":[], 
    "dependencies": ["[email protected][10.13.4.1558,)"], 
    "requiredMods": ["[email protected][10.13.4.1558,)"], 
    "useDependencyInformation": true 
    }] 
} 
+0

私はあなたの非常に徹底的な質問に感謝しますが、大きなブロックで注釈付きコードをそのまま置くことができますか?読み易い –

+0

@MattFletcher https://pastebin.com/XdMLZ0rd – WildeMe

+0

'modinfo'を使用するコードは全てコメントアウトされています。あなたは何のコールバックを話していますか? – Barmar

答えて

0

問題は、私はmodlistを使用していたということでした私modListのnstead。それは動作しません!ソリューションをありがとうBarmar

+0

Aaaaah haha​​、classic:D –

関連する問題