2011-06-18 35 views
191

Làm cách nào để phát hiện xem tệp Node.JS của tôi có được gọi là SH: node path-to-file hoặc JS: require('path-to-file')?Node.JS: Phát hiện nếu được gọi qua yêu cầu hoặc trực tiếp bằng dòng lệnh

Đây là Node.js tương đương với câu hỏi trước của tôi trong Perl: How can I run my Perl script only if it wasn't loaded with require?

+1

Bản sao có thể có của [node.js tương đương với python's nếu \ _ \ _ name \ _ \ _ == '\ _ \ _ main \ _ \ _'] (http://stackoverflow.com/question/4981891/node-js-equivalent-of-pythons-if-name-main) – GingerPlusPlus

Trả lời

297
if (require.main === module) { 
    console.log('called directly'); 
} else { 
    console.log('required as a module'); 
} 

Xem tài liệu hướng dẫn cho điều này ở đây: https://nodejs.org/docs/latest/api/all.html#modules_accessing_the_main_module

+0

cảm ơn Nicolas (và Jesse) –

+2

Có cách nào để giải quyết vấn đề này không? Tôi có mã (mà tôi không có quyền kiểm soát) mà làm điều này, nhưng tôi cần phải yêu cầu() nó và có nó hoạt động như thể nó được gọi trực tiếp. Về cơ bản, tôi cần phải đánh lừa một cái gì đó mà sử dụng thử nghiệm đó vào suy nghĩ nó được gọi trực tiếp. – Kevin

+2

@Kevin Tôi không biết làm điều này với 'require()', nhưng bạn có thể làm điều đó bằng cách nhập tệp sau đó chạy 'eval' trên nó, hoặc bằng cách chạy' require ('child_process'). 'node the_file.js') ' – MalcolmOcean

58

Có một cách hơi ngắn hơn (không được nêu trong đề cập tài liệu).

var runningAsScript = !module.parent;

tôi nêu thêm chi tiết về cách thức này tất cả các công trình dưới mui xe trong this blog post.

+0

+1, tôi thích điều này tốt hơn, nhưng tôi sẽ ngần ngại trước khi chuyển đổi câu trả lời được chấp nhận. :) –

+8

Như tôi đã chỉ ra, cách chính thức được ghi lại là một trong những @nicolaskruchten được vạch ra. Đây chỉ là một thay thế, không cần phải chuyển đổi câu trả lời được chấp nhận. Cả hai đều hoạt động. –

+1

Tôi đã phải sử dụng điều này chứ không phải là cách tài liệu - cách tài liệu hoạt động cho ví dụ. 'node script.js' nhưng không phải' cat script.js | nút'. Cách này hoạt động cho cả hai. –

2

Tôi hơi bối rối bởi thuật ngữ được sử dụng trong (các) giải thích. Vì vậy, tôi phải làm một vài bài kiểm tra nhanh.

tôi thấy rằng những tạo ra kết quả tương tự:

var isCLI = !module.parent; 
var isCLI = require.main === module; 

Và đối với những người bị nhầm lẫn khác (và trả lời câu hỏi trực tiếp):

var isCLI = require.main === module; 
var wasRequired = !isCLI; 
1

Cũng giống như trong Python, tôi luôn luôn tìm thấy bản thân tôi đang cố nhớ cách viết đoạn mã chết tiệt này. Vì vậy, tôi quyết định tạo ra một mô-đun đơn giản cho nó. Nó đã cho tôi một chút để phát triển kể từ khi truy cập thông tin mô-đun của người gọi không phải là straighforward, nhưng nó là thú vị để xem làm thế nào nó có thể được thực hiện.

Vì vậy, ý tưởng là gọi mô-đun và hỏi xem mô-đun người gọi có phải là mô-đun chính hay không. Chúng ta phải tìm ra mô-đun của hàm người gọi. Cách tiếp cận đầu tiên của tôi là biến thể của câu trả lời được chấp nhận:

module.exports = function() { 
    return require.main === module.parent; 
}; 

Nhưng điều đó không được đảm bảo để hoạt động. module.parent trỏ đến mô-đun mà tải chúng tôi vào bộ nhớ, chứ không phải người gọi cho chúng tôi. Nếu đó là mô-đun người gọi đã tải mô-đun trợ giúp này vào bộ nhớ thì điều đó là tốt. Nhưng nếu không, chúng tôi bất lực. Vì vậy, chúng ta cần phải thử cái gì khác. Giải pháp của tôi là để tạo ra một vết đống và nhận được tên module của người gọi từ đó:

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; 
}; 

Bây giờ chúng ta có thể làm:

if (require("./is-main-module")()) { // notice the `()` at the end 
    // do something 
} else { 
    // do something else 
} 

Hoặc dễ đọc hơn:

const isMainModule = require("./is-main-module"); 

if (isMainModule()) { 
    // do something 
} else { 
    // do something else 
} 

Impossible để quên :-)

+0

Rất tuyệt. Tôi thích nó khi đoạn mã phổ biến được viết tắt thành một tên duy nhất. Điều chỉnh nhỏ: 'return require.main/* điều này là không xác định nếu chúng ta bắt đầu nút tương tác */&& require.main.filename === callerModuleName;' – masterxilo

Các vấn đề liên quan