私はアーカイブから指定されたファイルを抽出し、コールバックであり、コンテンツを与えることができ、コードを持っているすべての最初の、だから... ...何でも、いくつかの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
}]
}
私はあなたの非常に徹底的な質問に感謝しますが、大きなブロックで注釈付きコードをそのまま置くことができますか?読み易い –
@MattFletcher https://pastebin.com/XdMLZ0rd – WildeMe
'modinfo'を使用するコードは全てコメントアウトされています。あなたは何のコールバックを話していますか? – Barmar