ฉันจะตรวจสอบว่าไฟล์ Node.js ของฉันถูกเรียกใช้ SH: node path-to-file
หรือ JS: require('path-to-file')
?
นี่คือ Node.JS เทียบเท่ากับคำถามก่อนหน้าของฉันใน Perl: ฉันจะรันสคริปต์ Perl ของฉันได้อย่างไรหากไม่ได้โหลดมาพร้อมกับจำเป็นต้องใช้?
ฉันจะตรวจสอบว่าไฟล์ Node.js ของฉันถูกเรียกใช้ SH: node path-to-file
หรือ JS: require('path-to-file')
?
นี่คือ Node.JS เทียบเท่ากับคำถามก่อนหน้าของฉันใน Perl: ฉันจะรันสคริปต์ Perl ของฉันได้อย่างไรหากไม่ได้โหลดมาพร้อมกับจำเป็นต้องใช้?
คำตอบ:
if (require.main === module) {
console.log('called directly');
} else {
console.log('required as a module');
}
ดูเอกสารสำหรับที่นี่: https://nodejs.org/docs/latest/api/modules.html#modules_accessing_the_main_module
require()
แต่คุณสามารถทำได้ด้วยการนำเข้าไฟล์จากนั้นก็รันeval
บนมันหรือโดยการเรียกใช้require('child_process').exec('node the_file.js')
es-main
แพ็คเกจเพื่อตรวจสอบว่ามีการเรียกใช้โมดูลโดยตรง
มีอีกวิธีที่สั้นกว่าเล็กน้อย (ไม่ได้ระบุไว้ในเอกสารที่กล่าวถึง)
var runningAsScript = !module.parent;
ฉันระบุรายละเอียดเพิ่มเติมเกี่ยวกับวิธีการทำงานทั้งหมดนี้ภายใต้ประทุนในโพสต์บล็อกนี้
node script.js
cat script.js | node
วิธีนี้ใช้ได้ผลกับทั้งคู่
ฉันสับสนเล็กน้อยโดยคำศัพท์ที่ใช้ในคำอธิบาย ดังนั้นฉันจึงต้องทำแบบทดสอบสองสามฉบับ
ฉันพบว่าสิ่งเหล่านี้ให้ผลลัพธ์ที่เหมือนกัน:
var isCLI = !module.parent;
var isCLI = require.main === module;
และสำหรับคนที่สับสนอื่น ๆ (และเพื่อตอบคำถามโดยตรง):
var isCLI = require.main === module;
var wasRequired = !isCLI;
เช่นเดียวกับใน Python ฉันมักจะพบว่าตัวเองพยายามจดจำวิธีการเขียนข้อมูลโค้ดนี้ ดังนั้นฉันตัดสินใจที่จะสร้างโมดูลง่าย ๆ สำหรับมัน ฉันใช้เวลาเล็กน้อยในการพัฒนาเนื่องจากการเข้าถึงข้อมูลโมดูลของผู้โทรไม่ได้ตรงไปตรงมา แต่มันสนุกที่ได้เห็นว่ามันสามารถทำได้
ดังนั้นความคิดคือการเรียกโมดูลและถามว่าโมดูลผู้โทรเป็นหลักหรือไม่ เราต้องหาโมดุลของฟังก์ชั่นผู้โทร วิธีแรกของฉันคือรูปแบบของคำตอบที่ยอมรับได้:
module.exports = function () {
return require.main === module.parent;
};
แต่นั่นไม่รับประกันว่าจะทำงาน module.parent
ชี้ไปที่โมดูลซึ่งโหลดเราลงในหน่วยความจำไม่ใช่ตัวเรียกเรา หากเป็นโมดูลผู้โทรที่โหลดโมดูลตัวช่วยนี้ลงในหน่วยความจำก็ถือว่าใช้ได้ แต่ถ้าไม่ใช่เราก็ไร้ประโยชน์ ดังนั้นเราต้องลองอย่างอื่น โซลูชันของฉันคือสร้างการติดตามสแต็กและรับชื่อโมดูลของผู้โทรจากที่นั่น:
module.exports = function () {
// generate a stack trace
const stack = (new Error()).stack;
// the third line refers to our caller
const stackLine = stack.split("\n")[2];
// extract the module name from that line
const callerModuleName = /\((.*):\d+:\d+\)$/.exec(stackLine)[1];
return require.main.filename === callerModuleName;
};
ตอนนี้เราสามารถทำได้:
if (require("./is-main-module")()) { // notice the `()` at the end
// do something
} else {
// do something else
}
หรืออ่านได้มากขึ้น:
const isMainModule = require("./is-main-module");
if (isMainModule()) {
// do something
} else {
// do something else
}
เป็นไปไม่ได้ที่จะลืม :-)
return require.main /*this is undefined if we started node interactively*/ && require.main.filename === callerModuleName;
ลองใช้วิธีนี้หากคุณใช้โมดูล ES6:
if (process.mainModule.filename === __filename) {
console.log('running as main module')
}
process.mainModule
คือundefined