जावास्क्रिप्ट कॉलर फ़ंक्शन लाइन नंबर कैसे प्राप्त करें? जावास्क्रिप्ट कॉलर स्रोत URL कैसे प्राप्त करें?


109

मैं जावास्क्रिप्ट कॉलर फ़ंक्शन नाम प्राप्त करने के लिए निम्नलिखित का उपयोग कर रहा हूं:

var callerFunc = arguments.callee.caller.toString();
callerFuncName = (callerFunc.substring(callerFunc.indexOf("function") + 8, callerFunc.indexOf("(")) || "anoynmous")

क्या उस रेखा संख्या की खोज करने का कोई तरीका है जिससे विधि को बुलाया गया था?

इसके अलावा, क्या जावास्क्रिप्ट फ़ाइल का नाम प्राप्त करने का एक तरीका है जिसे विधि कहा जाता है? या स्रोत URL?


2
मुझे नहीं लगता कि यह IE में संभव है, या फिर हमारे पास वहाँ कोई त्रुटि संदेश भेजने के लिए एक रास्ता होगा जो कोई विवरण नहीं देता है। लेकिन अगर यह संभव है तो मैं भी जानना चाहूंगा!
Zoidberg

हाँ। यहां एक क्रॉस-ब्राउज़र फ़ंक्शन है जो प्रत्येक ब्राउज़र के मालिकाना तरीकों का उपयोग करता है: github.com/eriwen/javascript-stacktrace [फिक्स्ड लिंक]
स्कैट्स

जवाबों:


99

यह मेरे लिए chrome / QtWebView में काम करता है

function getErrorObject(){
    try { throw Error('') } catch(err) { return err; }
}

var err = getErrorObject();
var caller_line = err.stack.split("\n")[4];
var index = caller_line.indexOf("at ");
var clean = caller_line.slice(index+2, caller_line.length);

नोड में भी काम करता है। अपने कस्टम लॉग () फ़ंक्शन के अंदर इसे पॉप करें (जो आपके लिए आवश्यक अन्य उपयोगी वर्कअराउंड जोड़ता है - जैसे क्रोम ऐरे लॉगिंग के लिए तय किया गया है) और अभी भी जहाँ भी आप लॉग () कहते हैं उससे संख्याओं को पंक्तिबद्ध करें।
मिकमेकाना

60
त्रुटि फेंकने की आवश्यकता नहीं है; बस इसे बनाना काफी है:var caller_line = (new Error).stack.split("\n")[4]
ELLIOTTCABLE

2
एफएफ / वेबकिट "मानकीकृत" प्रतिक्रिया प्राप्त करने के लिए इसी तरह के एक और जवाब के साथ इस सुझाव को मिला दिया - देखें stackoverflow.com/a/14841411/1037948
drzaus

1
PhantomJS में भी काम करता है, लेकिन आपको इसे फेंकना होगा, अन्यथा त्रुटि पर "स्टैक" विशेषता सेट नहीं है।
जोशुआ रिचर्डसन

1
@ आईओएस सफारी जैसे कुछ ब्राउज़रों में वास्तविक नाम आपको अपवाद को फेंकने की आवश्यकता है! तो क्यों नहीं करते?
आर्केलिक्स

26

kangax का समाधान अनावश्यक प्रयास..चेक गुंजाइश का परिचय देता है। यदि आपको जावास्क्रिप्ट में कुछ की लाइन संख्या (जब तक आप फ़ायरफ़ॉक्स या ओपेरा का उपयोग कर रहे हैं) तक पहुंचने की आवश्यकता है, तो बस पहुंचें (new Error).lineNumber


11
नमस्ते, उस addon के लिए धन्यवाद। क्या आपको पता है कि पिछले कॉल से लाइन नंबर प्राप्त करना संभव है? विधि A को B कहते हैं, और अब BI में जानना चाहेंगे कि A कॉल के अंतर्गत किस पंक्ति में बना था?
ताल

85
यह टिक गया है, लेकिन इस सवाल का जवाब नहीं देता है कि कॉल करने वाले फ़ंक्शन की लाइन संख्या कैसे प्राप्त करें ।
मिकमेकाना

3
इसके अलावा, यह बेहद सीमित है। सबसे अच्छा समाधान एक त्रुटि को फेंकना और त्रुटि पर regex का उपयोग करना है। जो कि सभी आधुनिक ब्राउज़रों में उपलब्ध है। आप उस पथ, फ़ाइल, रेखा और स्तंभ को आसानी से निकाल सकते हैं। कोई दिक्कत नहीं है।
आर्केलिक्स

13

मुझे आश्चर्य हुआ कि इनमें से अधिकांश उत्तरों ने मान लिया था कि आप सामान्य मामलों के लिए भी आउटपुट डिबग ट्रैस के बजाय एक त्रुटि को संभालना चाहते थे।

उदाहरण के लिए, मुझे console.logइस तरह के रैपर का उपयोग करना पसंद है:

consoleLog = function(msg) {//See https://stackoverflow.com/a/27074218/470749
    var e = new Error();
    if (!e.stack)
        try {
            // IE requires the Error to actually be thrown or else the 
            // Error's 'stack' property is undefined.
            throw e;
        } catch (e) {
            if (!e.stack) {
                //return 0; // IE < 10, likely
            }
        }
    var stack = e.stack.toString().split(/\r\n|\n/);
    if (msg === '') {
        msg = '""';
    }
    console.log(msg, '          [' + stack[1] + ']');        
}

यह मेरे कंसोल के लिए निम्न के रूप में एक आउटपुट प्रिंट करना समाप्त करता है:

1462567104174 [getAllPosts@http://me.com/helper.js:362:9]

Https://stackoverflow.com/a/27074218/ और भी सही लाइन नंबर के साथ कंसोल.लॉग के लिए एक उचित आवरण देखें ?


1
फ़ायरफ़ॉक्स ब्राउज़र के लिए काम करता है, लेकिन नोड के लिए काम नहीं करता है। जेसे
जिपर

1
नोड के तहत आपको स्टैक लॉग करना होगा [2]
मोनिका मेवेनकैंप

5

यह अक्सर वर्तमान संदर्भ से एक त्रुटि फेंककर प्राप्त किया जाता है; तब गुणों के लिए त्रुटि ऑब्जेक्ट का विश्लेषण करना lineNumberऔर fileName(जो कुछ ब्राउज़र में है)

function getErrorObject(){
  try { throw Error('') } catch(err) { return err; }
}

var err = getErrorObject();

err.fileName;
err.lineNumber; // or `err.line` in WebKit

यह मत भूलो कि callee.callerसंपत्ति को पदावनत कर दिया गया है (और वास्तव में ईसीएमए 3 एड में पहले स्थान पर नहीं था)।

यह भी याद रखें कि फ़ंक्शन विघटन को कार्यान्वयन पर निर्भर होना निर्दिष्ट है और इसलिए काफी अप्रत्याशित परिणाम मिल सकते हैं। मैंने इसके बारे में यहां और यहां लिखा है


धन्यवाद, मुझे इस कोड को उस एप्लिकेशन में जोड़ना थोड़ा समस्याजनक लगता है जिसकी मुझे आवश्यकता है। (कुछ js ट्रेसिंग फ्रेमवर्क) क्या आप किसी अन्य विधि को जानते हैं जो कि उपयोग में नहीं ली गई है?
ताल

आपको पदावनत किए गए भरोसे के बिना त्रुटि वस्तु का निरीक्षण करने में सक्षम होना चाहिए callee.caller
kangax

आपको त्रुटि फेंकने की आवश्यकता नहीं है। आप बस (नई त्रुटि) .lineNumber का उपयोग एक स्क्रिप्ट में वर्तमान लाइन नंबर तक पहुँचने के लिए करते हैं।
एली ग्रे

@ एलिजा यह वही है जो मैं एफएफ 3 में देखता हूं। दूसरी ओर, WebKit, lineकेवल पॉप्युलेट करता है जब त्रुटि डाली जाती है।
23

Callee.caller का विकल्प क्या है? अगर मुझे फ़ंक्शन नाम प्राप्त करने की आवश्यकता है?
ताल

4

ऐसा लगता है कि मैं बहुत देर से हूं :), लेकिन चर्चा बहुत दिलचस्प है .. इसलिए यहाँ पर ... यह मानते हुए कि आप एक त्रुटि हैंडलर बनाना चाहते हैं, और आप अपने स्वयं के अपवाद हैंडलर वर्ग का उपयोग कर रहे हैं:

function  errorHandler(error){
    this.errorMessage = error;
}
errorHandler.prototype. displayErrors = function(){
    throw new Error(this.errorMessage);
}

और आप अपना कोड इस तरह से लपेट रहे हैं:

try{
if(condition){
    //whatever...
}else{
    throw new errorHandler('Some Error Message');
}
}catch(e){
    e.displayErrors();
}

सबसे शायद आपके पास एक अलग .js फ़ाइल में त्रुटि हैंडलर होगा।

आप देखेंगे कि फ़ायरफ़ॉक्स या क्रोम की त्रुटि में कोड लाइन नंबर (और फ़ाइल का नाम) दिखाया गया कंसोल लाइन (फ़ाइल) है जो 'त्रुटि' अपवाद को फेंकता है और 'एररहैंडलर' अपवाद को नहीं जो आप वास्तव में डिबगिंग बनाने के लिए चाहते हैं। आसान। अपने स्वयं के अपवादों को फेंकना महान है लेकिन बड़ी परियोजनाओं पर उनका पता लगाना काफी मुद्दा हो सकता है, खासकर यदि उनके पास समान संदेश हैं। तो, आप क्या कर सकते हैं अपनी त्रुटि हैंडलर के लिए एक वास्तविक खाली त्रुटि ऑब्जेक्ट का संदर्भ पास करना है, और वह संदर्भ आपके द्वारा वांछित सभी जानकारी रखेगा (उदाहरण के लिए फ़ायरफ़ॉक्स में आप फ़ाइल का नाम, और लाइन नंबर आदि प्राप्त कर सकते हैं)। क्रोम में आपको कुछ ऐसा ही मिलता है यदि आप 'त्रुटि उदाहरण के स्टैक' संपत्ति को पढ़ते हैं)। लंबी कहानी छोटी, आप कुछ इस तरह कर सकते हैं:

function  errorHandler(error, errorInstance){
    this.errorMessage = error;
    this. errorInstance = errorInstance;
}
errorHandler.prototype. displayErrors = function(){
    //add the empty error trace to your message
    this.errorMessage += '  stack trace: '+ this. errorInstance.stack;
    throw new Error(this.errorMessage);
}

try{
if(condition){
    //whatever...
}else{
    throw new errorHandler('Some Error Message', new Error());
}
}catch(e){
    e.displayErrors();
}

अब आप वास्तविक फ़ाइल और लाइन नंबर प्राप्त कर सकते हैं जिसने आपको कस्टम अपवाद फेंक दिया है।


4

लाइन नंबर वास्तव में कुछ स्थिर है, इसलिए यदि आप इसे लॉगिंग के लिए चाहते हैं, तो यह कुछ गुल जैसी चीज के साथ पहले से रखा जा सकता है। मैंने एक छोटा सा gulp प्लगइन लिखा है जो बिल्कुल ऐसा करता है:

var gulp = require('gulp');
var logLine = require('gulp-log-line');
gulp.task('log-line', function() {
    return gulp.src("file.js", {buffer : true})
    //Write here the loggers you use.
        .pipe(logLine(['console.log']))
        .pipe(gulp.dest('./build'))

})

gulp.task('default', ['log-line'])

यह फ़ाइल नाम और लाइन को सभी लॉग्स से कंसोल.लॉग से जोड़ेगा, इसलिए console.log(something)यह बन जाएगा console.log('filePath:fileNumber', something)। लाभ यह है कि अब आप अपनी फ़ाइलों को संक्षिप्त कर सकते हैं, उन्हें स्थानांतरित कर सकते हैं ... और आप अभी भी लाइन प्राप्त करेंगे


यह उन स्थितियों के लिए एक महान सुझाव की तरह लगता है जहां एक ट्रांसपिलर का उपयोग किया जाता है (जैसे, टाइपस्क्रिप्ट का उपयोग करते समय)। धन्यवाद!
एंडी राजा

4

मुझे लगता है कि यह एक पुराना प्रश्न है, लेकिन अब एक विधि है जिसे कहा जाता है console.trace("Message")कि आपको लाइन नंबर और विधि कॉल की श्रृंखला दिखाई देगी, जिसके कारण आप इसे पास करने वाले संदेश के साथ लॉग इन करेंगे। जावास्क्रिप्ट लॉगिंग ट्रिक्स के बारे में अधिक जानकारी यहां फ्रीकोडेकैम्प और इस माध्यम ब्लॉग पोस्ट पर उपलब्ध है


3

यदि आप डिबगिंग उद्देश्यों के लिए लाइन नंबर जानना चाहते हैं, या केवल विकास के दौरान (एक कारण या किसी अन्य के लिए), तो आप फायरबग (फ़ायरफ़ॉक्स एक्सटेंशन) का उपयोग कर सकते हैं और एक अपवाद फेंक सकते हैं।

संपादित करें :

यदि आपको वास्तव में किसी कारण से ऐसा करने की आवश्यकता है, तो आप प्रत्येक फ़ंक्शन के लिए अपनी जावास्क्रिप्ट फ़ाइलों को पूर्व-प्रक्रिया कर सकते हैं ताकि वह जिस लाइन पर है, उसका ट्रैक रख सके। मुझे पता है कि कुछ फ्रेमवर्क हैं जो कोड के कवरेज का उपयोग करते हैं (जैसे कि JSCoverage )।

उदाहरण के लिए, मान लें कि आपका मूल कॉल है:

function x() {
  1 + 1;
  2 + 2;
  y();
}

आप इसे बनाने के लिए एक पूर्वप्रक्रमक लिख सकते हैं:

function x() {
  var me = arguments.callee;
  me.line = 1;
  1 + 1;
  me.line = 2;
  2 + 2;
  me.line = 3;
  y();
}

फिर y(), आप arguments.callee.caller.lineउस रेखा को जानने के लिए उपयोग कर सकते हैं जिससे इसे बुलाया गया था, जैसे:

function y() {
  alert(arguments.callee.caller.line);
}

1
धन्यवाद, मैं समर्थन कारणों के लिए उत्पादन में यह करना चाहूंगा। मुझे कुछ कोड मिले हैं जो आपको विधि तक सभी प्रवाह के कॉल स्टैक को देखने में सक्षम बनाते हैं, लेकिन इसमें उन रेखाओं की संख्या नहीं होती है जहाँ विधियों को बुलाया गया था। मैं उस के लिए आसान समाधान लगता है?
ताल

3

यह मैंने कैसे किया है, मैंने इसे फ़ायरफ़ॉक्स और क्रोम दोनों में परीक्षण किया है। यह उस स्थान के फ़ाइल नाम और लाइन नंबर की जांच करना संभव बनाता है जहां से फ़ंक्शन को बुलाया जाता है।

logFileAndLineNumber(new Error());

function logFileAndLineNumber(newErr)
{
   if(navigator.userAgent.indexOf("Firefox") != -1)
   {
      var originPath = newErr.stack.split('\n')[0].split("/");
      var fileNameAndLineNumber = originPath[originPath.length - 1].split(">")[0];
      console.log(fileNameAndLineNumber);
   }else if(navigator.userAgent.indexOf("Chrome") != -1)
   {
      var originFile = newErr.stack.split('\n')[1].split('/');
      var fileName = originFile[originFile.length - 1].split(':')[0];
      var lineNumber = originFile[originFile.length - 1].split(':')[1];
      console.log(fileName+" line "+lineNumber);
    }
}

2

इस मंच पर मिली जानकारी के आधार पर मैंने यहां क्या लिखा है:

यह MyDebugNamespace का एक हिस्सा है, डिबग जाहिरा तौर पर आरक्षित है और नामस्थान नाम के रूप में नहीं करेगा।

    var DEBUG = true;

...

    if (true == DEBUG && !test)
    {
        var sAlert = "Assertion failed! ";
        if (null != message)
            sAlert += "\n" + message;
        if (null != err)
            sAlert += "\n" + "File: " + err.fileName + "\n" + "Line: " + err.lineNumber;
        alert(sAlert);
    }

...

कैसे कॉल करें:

    MyDebugNamespace.Assert(new Error(""), (null != someVar), "Something is wrong!")

मैंने अपने नाम स्थान में इस आधार कोड को कॉल करने वाले तर्कों की चर संख्या के साथ दो कार्य शामिल किए ताकि वैकल्पिक रूप से संदेश या कॉल में त्रुटि न हो।

यह फ़ायरफ़ॉक्स, IE6 और Chrome के साथ ठीक काम करता है फ़ाइल का नाम और लाइन नॉन को अपरिभाषित के रूप में रिपोर्ट करता है।


2

निम्नलिखित कोड मोज़िला और क्रोम में मेरे लिए काम करता है।

इसका लॉग फ़ंक्शन जो फ़ाइल का नाम और कॉलर की लाइन दिखाता है।

log: function (arg) {
    var toPrint = [];
    for (var i = 0; i < arguments.length; ++i) {
        toPrint.push(arguments[i]);
    }

    function getErrorObject(){
        try { throw Error('') } catch(err) { return err; }
    }

    var err = getErrorObject(),
        caller;

    if ($.browser.mozilla) {
        caller = err.stack.split("\n")[2];
    } else {
        caller = err.stack.split("\n")[4];
    }

    var index = caller.indexOf('.js');

    var str = caller.substr(0, index + 3);
    index = str.lastIndexOf('/');
    str = str.substr(index + 1, str.length);

    var info = "\t\tFile: " + str;

    if ($.browser.mozilla) {
        str = caller;
    } else {
        index = caller.lastIndexOf(':');
        str = caller.substr(0, index);
    }
    index = str.lastIndexOf(':');
    str = str.substr(index + 1, str.length);
    info += " Line: " + str;
    toPrint.push(info);

    console.log.apply(console, toPrint);
}

लगता है जैसे कुछ गायब है। मुझे मिलता है:SyntaxError: function statement requires a name,log: function (arg) {
spiderplant0

मुझे यह विचार पसंद है, लेकिन मेरे लिए लाइन नंबर गलत हैं।
रयान

2

जावास्क्रिप्ट में कस्टम त्रुटियों के लिए मेरा योगदान:

  1. सबसे पहले, मैं त्रुटि ऑब्जेक्ट से इनहेरिटिंग में इस @BT आदमी से सहमत हूं - संदेश संपत्ति कहां है? , हमने इसे ठीक से बनाया है (वास्तव में आपको एक js ऑब्जेक्ट लाइब्रेरी का उपयोग करना है, मेरा पसंदीदा: https://github.com/jiem/my-class ):

    window.g3 = window.g3 || {};
    g3.Error = function (message, name, original) {
         this.original = original;
         this.name = name || 'Error.g3';
         this.message = message || 'A g3.Error was thrown!';
         (original)? this.stack = this.original.stack: this.stack = null;
         this.message += '<br>---STACK---<br>' + this.stack;
     };
    
     var ClassEmpty = function() {};
     ClassEmpty.prototype = Error.prototype;
     g3.Error.prototype = new ClassEmpty();
     g3.Error.prototype.constructor = g3.Error;
  2. फिर, हमें एक वैश्विक त्रुटि हैंडलिंग फ़ंक्शन (वैकल्पिक) को परिभाषित करना चाहिए या, वे इंजन तक समाप्त हो जाएंगे:

    window.onerror = printError; 
    function printError(msg, url, line){
        document.getElementById('test').innerHTML = msg+'<br>at: '+url+'<br>line: '+line;
        return true;
    }
  3. अंत में, हमें अपनी कस्टम त्रुटियों को सावधानी से फेंकना चाहिए:

    //hit it!
    //throw new g3.Error('Hey, this is an error message!', 'Error.Factory.g3');
    throw new g3.Error('Hey, this is an error message!', 'Error.Factory.g3', new Error());

केवल तीसरे पैरामीटर को पास करते समय, जब new Error()हम फ़ंक्शन और लाइन नंबरों के साथ स्टैक को देखने में सक्षम होते हैं!

2 पर, फ़ंक्शन इंजन द्वारा फेंकी गई त्रुटि को भी संभाल सकता है।

बेशक, असली सवाल यह है कि क्या हमें वास्तव में इसकी आवश्यकता है और कब; ऐसे मामले (मेरी राय में ९९%) हैं, जहां एक शानदार वापसी falseपर्याप्त है और केवल कुछ महत्वपूर्ण बिंदुओं को एक त्रुटि के फेंकने के साथ दिखाया जाना छोड़ दें।

उदाहरण: http://jsfiddle.net/centurianii/m2sQ3/1/


2
console.log(new Error);

यह आपको पूरा ट्रैक दिखाएगा।


1

यह निर्धारित करने के लिए कि आपको कौन सी रेखा है, आपको उस कोड के लिए सभी कोड को खोजना होगा जो ब्याज की विशेष रेखा पर है और "\ n" वर्णों को ऊपर से इस ब्याज पर गिनें और 1 जोड़ें।

मैं वास्तव में यह एक ऐसा काम कर रहा हूं जो मैं लिख रहा हूं। यह HTML के लिए सबसे अच्छा व्यवहार सत्यापनकर्ता है और अभी भी विकास के तहत भारी है, लेकिन त्रुटि आउटपुट प्रक्रिया जिसे आप रुचि रखते हैं, वह पूर्ण है।

http://mailmarkup.org/htmlint/htmlint.html


ब्याज की विशेष पंक्ति कई हो सकती है ... यदि मेरे पास एक ही विधि है जिसे किसी अन्य विधि से कई बार कॉल किया जाता है, तो मुझे कैसे पता चल सकता है (उस अन्य विधि में) जहां से कॉल आई थी?
ताल

आप दुभाषिया के बाहर से निष्पादन समय पर जावास्क्रिप्ट व्याख्या का विश्लेषण करने में सक्षम नहीं होने जा रहे हैं। आप अपने कार्यक्रम में निष्पादन पथ का पता लगाने के लिए एक कार्यक्रम लिख सकते हैं, लेकिन यह वह कार्यक्रम होगा जो निष्पादित कर रहा है और उस कोड को नहीं जिसे आप विश्लेषण करना चाहते हैं। यह आमतौर पर एक जटिल कार्य है जो कि टूल की मदद से मैन्युअल रूप से किया जाता है। यदि आप वास्तव में यह देखना चाहते हैं कि आपके कोड में क्या हो रहा है क्योंकि यह निष्पादित होता है, तो क्या इसने स्क्रीन पर मेटा-डेटा लिखा है जो बताता है कि आप निर्णय चाहते हैं जो अन्य भागों को निष्पादित कर रहे हैं।

-2

उत्तर सरल हैं। नहीं और नहीं (नहीं)।

जब तक जावास्क्रिप्ट स्रोत फ़ाइलों / urls की अवधारणा को चला रहा होता है, जिसमें से चला जाता है।

लाइन संख्या निर्धारित करने का कोई तरीका भी नहीं है क्योंकि फिर से निष्पादन के समय तक कोड "लाइनों" की धारणा जावास्क्रिप्ट में सार्थक नहीं है।

विशिष्ट कार्यान्वयन डिबगिंग के उद्देश्य से निजीकृत कोड को ऐसे विवरणों तक पहुंच की अनुमति देने के लिए एपीआई हुक प्रदान कर सकते हैं लेकिन ये एपीआई सामान्य मानक जावास्क्रिप्ट कोड के संपर्क में नहीं आते हैं।


फ़ायरफ़ॉक्स में अपवादों में ऐसी जानकारी शामिल है ... क्या कम से कम फ़ायरफ़ॉक्स में यह संभव होगा?
Zoidberg

जब आप MS स्क्रिप्ट डीबगर लॉन्च करते हैं और कुछ ब्रेकपॉइंट डालते हैं, तो आप कॉल स्टैक में देखते हैं कि वास्तव में आप कहाँ से आए थे। यह विशेष हुक के कारण है?
ताल

"फिर से निष्पादन के समय तक कोड" लाइनों "की धारणा जावास्क्रिप्ट में सार्थक नहीं है।" है ना? JS पहले ही लाइन नंबर दिखाता है जो आप
कंसोल

@AnthonyWJones हाँ। यह बड़े करीने से निरपेक्ष 'नहीं और नहीं (नहीं) का विरोधाभासी है।'
मिकमेकाना 10

@ नेलर: सभी प्रमुख ब्राउज़रों में 2009 में वापस, किस तरह से मेरा उत्तर विरोधाभासी है। भालू के मन में यह सवाल है कि खोज के बारे में, चल रही जावास्क्रिप्ट में, कैलली की रेखा संख्या के बारे में क्या है?
एंथनीवजोन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.