返回JavaScript代码时如何在PHP / Dojo中正确生成异常 [英] How to properly generate exceptions in PHP/Dojo when returning javascript code

查看:139
本文介绍了返回JavaScript代码时如何在PHP / Dojo中正确生成异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很难理解通过AJAX动态获取代码并通过 eval 执行代码时如何处理异常。使用客户端javascript,它是相当简单的,如果我有一段代码,如这个

I am having difficulty understanding how exceptions are handled when code is fetched dynamically via AJAX and executed via eval. With clientside javascript, it is rather simple, if I have a piece of code such as this

var j = 'some string';
j.propA.x++;

这将引发异常,因为 propA 其类型为 undefined 没有 x 。此外,提出的异常非常容易理解。

this will raise an exception because propA, which is of type undefined does not have an x. Furthermore, the exception raised is very easy to understand.

现在让上面的代码放在一个文本文件中,让它调用它 test.js ,并将其存储在服务器上。现在可以使用Ajax动态加载它。我正在使用以下代码来动态加载它。

Now lets put the above code in a text file, lets call it test.js, and store it on the server. Now lets load it dynamically with Ajax. I am using the following code to load it dynamically

dojo.xhrGet({
  url: 'load.php',
  handleAs: "javascript",
  content : {
    fileName : 'test.js'
  },
  load: function(returnValue) {
    /*Do Something*/
  },
  error: function(errorMessage) {
    /*Report Error*/
  }
});

这是一个非常基本的php脚本,用于加载文件并将其作为JavaScript代码返回

Here is a very basic php script for loading the file and returning it as javascript code

<?php
  $fileName = $_GET['fileName'];
  $handle = fopen($fileName , 'r');
  $script = fread($handle, filesize($fileName));
  fclose($handle);
  echo $script;
?>

在上述 dojo.xhrGet 可以将错误属性设置为显示错误消息的功能,以下是可以完成的许多方法的一个示例。

In the above dojo.xhrGet call, the error property can be set to a function to display the error message, here is an example of some of the many ways this can be done.

error: function(errorMessage) {
  console.error(errorMessage);
  console.error(errorMessage.arguments);
  console.error(errorMessage.message);
  console.error(errorMessage.stack);
  console.error(errorMessage.type);
}

以下是输出示例。虽然这个输出是一个不同的问题,但它突出显示了它是多么难以理解的:

Below is an example of the output. Although this output is for a different problem, it highlights how incomprehensible it is:

Cannot read property 'x' of undefined
TypeError: Cannot read property 'x' of undefined
    at eval at <anonymous> (http://o.aolcdn.com/dojo/1.6/dojo/dojo.xd.js:14:3088)
    at Object.load (http://192.168.1.8/easel.js:166:6)
    at http://o.aolcdn.com/dojo/1.6/dojo/dojo.xd.js:14:89998
    at _144 (http://o.aolcdn.com/dojo/1.6/dojo/dojo.xd.js:14:36518)
    at _142 (http://o.aolcdn.com/dojo/1.6/dojo/dojo.xd.js:14:36328)
    at [object Object].<anonymous> (http://o.aolcdn.com/dojo/1.6/dojo/dojo.xd.js:14:36994)
    at _144 (http://o.aolcdn.com/dojo/1.6/dojo/dojo.xd.js:14:36780)
    at _142 (http://o.aolcdn.com/dojo/1.6/dojo/dojo.xd.js:14:36328)
    at [object Object].<anonymous> (http://o.aolcdn.com/dojo/1.6/dojo/dojo.xd.js:14:36994)
    at Object.resHandle (http://o.aolcdn.com/dojo/1.6/dojo/dojo.xd.js:14:92730)
non_object_property_load

我假设 dojo.xd.js:14 eval 语句的行。

如果知道他们正在寻找什么,上述可能就足够了。但是,在 eval

If one knows what they are looking for, the above might suffice. However, is there an easier, or at least a more productive way to deal with exceptions arising in eval?

这里是一个有点类似的问题。

Here is a somewhat similar question.

Phikin提供了一个好的解决方案,所以我给他了赏金。使用他的解决方案,我得到一个看起来像这样(我削减了一点)的输出。

Phikin provided a good solution to this problem below so I gave him the bounty. Using his solution, I got an output which looked something like this (I cut it down a bit)

    ReferenceError in JS Code detected: (url: module.require.php?module=MainMenu.Bg_S)
easel.js:211Error Message: ReferenceError: apple is not defined
easel.js:213(function(){
return function(args){
dojo.require("Shape");

Module.assert('MainMenu_V');

/**
* The rectangular background of the Main View
* @property MainMenuBg_S
* @type Shape
**/
new Shape({
    /**
    * Unique descriptive name used when later accessing this shape via '$$()'
    * @param name
    * @type String
    **/
    name : 'MainMenu.Bg_S' , 
    /**
    * Left side of this rectangle
    * @param x
    * @type Number
    **/             
    x : $$('MainMenu_V').x , 

    /**
    * Top of this rectangle
    * @param y
    * @type Number
    **/ 
    y : $$('MainMenu_V').y , 

    /**
    * Width of this rectangle
    * @param w
    * @type Number
    **/ 
    w : $$('MainMenu_V').w , 

    /**
    * Height of this rectangle
    * @param h
    * @type Number
    **/ 
    h : $$('MainMenu_V').h , 

    /**
    * Type of this Shape
    * @param h
    * @type Number
    **/ 
    type : shapeType.RECTANGLE , 

    /**
    * Generate function which contains all the graphics instructions, as well as the contexts
    * to preload and initialize. This is currently under development. Backgrounds should NEVER
    * have mouse events associated with them as a redraw of a background implies a redraw of 
    * every single displayObject infront of the background.
    * @param generate
    * @type method
    **/   
    generate : function (){
        var x = this.x << 0 , y = this.y << 0 , h = this.h << 0 , w = this.w << 0 , a = this.a;

        this.graphics(contextID.LEAVE).lf([hsl(180,100,60,0.9),hsl(180,100,20,0.75)],[0,1],0,h/2,w,h/2).dr(x,y,w,h).ef();
        this.graphics(contextID.ENTER).lf([hsl(135,100,40,0.9),hsl(135,100,20,0.75)],[0,1],0,h/2,w,h/2).dr(x,y,w,h).ef();
        this.graphics(contextID.CLICK).lf([hsl(90,100,40,0.9),hsl(90,50,20,0.75)],[0,1],0,h/2,w,h/2).dr(x,y,w,h).ef();
        this.graphics(contextID.RCLICK).lf([hsl(90,110,40,0.9),hsl(80,60,20,0.45)],[0,1],0,h/2,w,h/2).dr(x,y,w,h).ef();
        this.graphics(contextID.DBLCLICK).lf([hsl(45,100,40,0.9),hsl(45,100,20,0.75)],[0,1],0,h/2,w,h/2).dr(x,y,w,h).ef();
        this.graphics(contextID.DBLRCLICK).lf([hsl(10,100,40,0.9),hsl(10,100,20,0.75)],[0,1],0,h/2,w,h/2).dr(x,y,w,h).ef();
        this.graphics(contextID.LPRESS).lf([hsl(110,25,40,0.9),hsl(110,25,20,0.75)],[0,1],0,h/2,w,h/2).dr(x,y,w,h).ef();
        this.graphics(contextID.RPRESS).lf([hsl(110,50,40,0.9),hsl(110,50,20,0.75)],[0,1],0,h/2,w,h/2).dr(x,y,w,h).ef();
        this.graphics(contextID.SCROLL).lf([hsl(110,50,40,0.9),hsl(110,50,20,0.75)],[0,1],0,h/2,w,h/2).dr(x,y,w,h).ef();

        if (debugFlags.BOUNDINGBOX()){
            this.graphics(contextID.ENTER).ss(2).s(rgba(0,255,0,a)).dr(this.boundingBox.softBounds.L +4<<0, this.boundingBox.softBounds.T +4<<0, this.boundingBox.softBounds.w-8<<0 , this.boundingBox.softBounds.h-8<<0).es();
            this.graphics(contextID.ENTER).ss(2).s(rgba(255,0,0,a)).dr(this.boundingBox.bounds.L +4<<0, this.boundingBox.bounds.T +4<<0, this.boundingBox.bounds.w-8<<0 , this.boundingBox.bounds.h-8<<0).es();
            this.graphics(contextID.ENTER).f(rgba(0,0,255,a)).dc(this.boundingBox.points[0].x+4 , this.boundingBox.points[0].y+4 , 4).ef();
            this.graphics(contextID.ENTER).f(rgba(0,0,255,a)).dc(this.boundingBox.points[1].x-8 , this.boundingBox.points[1].y+4 , 4).ef();
            this.graphics(contextID.ENTER).f(rgba(0,0,255,a)).dc(this.boundingBox.points[2].x-8 , this.boundingBox.points[2].y-8 , 4).ef();
            this.graphics(contextID.ENTER).f(rgba(0,0,255,a)).dc(this.boundingBox.points[3].x+4 , this.boundingBox.points[3].y-8 , 4).ef();
        }
    },

    /**
    * Arguments to pass to the mouse initialization function. These will get mixed in (via
    * dojo.mixin) to the mouse object. To increase performance, the signalOrderIn has been set to
    * NOHIT. This will limit the number of redraws (remember background redraws are extremely
    * expensive as they require redrawing everything in the container). The signalOrderOut is 
    * then set to BLOCK to prvent anything behind the background from receiving mouse signals
    * (this is actually unecessary as the only think behind the background is, and always should
    * be, the container, which itself has signalOrderIn and signalOrderOut set to NOHIT and BLOCK
    * respectively).
    * @param mouse
    * @type Object
    **/ 
    mouse : {
        _signalOrderIN : signalFlags.NOHIT ,
        _signalOrderOUT : signalFlags.BLOCK
    } ,

    /** 
    * All views are initially loaded via Ajax. Generally, views do not have any preconditions, beyond
    * that the stage be present. They can, however, and generally do, have modules they require. These
    * are called after this view has been created and loaded (load() function call). They are called
    * in the order of the sub arrays. In the example below:
    * [[A , B , C , D , E , F , G]]
    * The 7 modules are requested in that order, but, due to Ajax, they can be loaded in any order. 
    * In the below example, on the other hand:
    * [[A] , [B , C , D , E , F , G]]
    * Modules B-G depend on module A, therefore, module A is ordered to be loaded first. 
    * @property providedModules
    * @type Array[Array[String]]
    * @protected
    **/
    providedModules : [[]] ,

    /** 
    * Carries out all the initializations when loading the module
    * @method load
    * @protected
    **/
    load : function (){
                0/apple;
        $$('MainMenu_V').addChild(this);
    } ,

    /** 
    * Carries out all memory deallocation when leaving the module (generally only necessary if modules
    * were loaded but not added to stage as in the case with cached bitmaps)
    * @method leave
    * @protected
    **/
    leave : function (){
    }
});
$$('MainMenu.Bg_S')._code="dojo.require(\"Shape\");...";
};
}());

easel.js:217Error triggered by: function (_2bd){return err.call(args,_2bd,_2b7);}
easel.js:220XHR Object:
easel.js:221
Object
args: Object
handleAs: "javascript"
query: null
url: "module.require.php?module=MainMenu.Bg_S"
xhr: XMLHttpRequest
__proto__: Object
easel.js:222Error Object:
easel.js:223
ReferenceError
arguments: Array[1]
message: "—"
stack: "—"
type: "not_defined"
__proto__: Error
dojo.xd.js:14
ReferenceError
arguments: Array[1]
message: "—"
stack: "—"
type: "not_defined"
__proto__: Error
dojo.xd.js:14
ReferenceError
arguments: Array[1]
message: "—"
stack: "—"
type: "not_defined"
__proto__: Error

我需要的唯一缺点是能够指出什么行发生问题。

The only thing it's missing, that I need, is the ability to indicate what line the problem occurred.

推荐答案

这是一个剪辑的帽子会从xhr-get请求中检测到非网络相关的错误,并在控制台中输出一些关于它的信息。

Here is a snipped that detectes non-network related errors from an xhr-get request and outputs some information about it in the console.

有一个额外的isEvalError()函数, eval-error类型...我不是很自豪。更好的方法可能是通过获取errorMessage子类的父对象。
我认为你可以一般来说沟通isEvalError(),因为这个块中不可能有任何其他错误。

There is an extra isEvalError() function that goes through all eval-error types... which I am not really proud of. A nicer way could be by getting the parent object of the errorMessage sub-classes. I think you can ditch isEvalError() generally, because there shouldn´t be any other error possible in this block.

function isEvalError(errorMessage){
    return errorMessage.name == "RangeError" ||
    errorMessage.name == "ReferenceError" ||
    errorMessage.name == "SyntaxError" ||
    errorMessage.name == "URIError" ||
    errorMessage.name == "TypeError";
}

var foo = dojo.xhrGet({
    url: 'stacko.js',
    handleAs: "javascript",
    load: function(returnValue) {
        console.log("load: "+returnValue);
    },
    error: function(errorMessage,ioargs) {

        //request worked fine, this must be a non-network related error
        if(ioargs.xhr.readyState == 4 && ioargs.xhr.status == 200) {


            if(isEvalError(errorMessage)){
                //show eval-error, url request & the JS code that causes the exception
                //eval-error types: RangeError,ReferenceError,SyntaxError, URIError, TypeError
                console.error(errorMessage.name+" in JS Code detected: (url: "+ioargs.url+")")
                console.error("Error Message: "+ errorMessage);

                console.error(ioargs.xhr.responseText);
            }

            //a little reflection - if u want to know who triggered this error 
            //(although in this case the output is not very helpful )
            console.error("Error triggered by: "+arguments.callee.caller.toString());

            //last but not least log the error & the xhr-request object for more information
            console.error("XHR Object:");
            console.error(ioargs);
            console.error("Error Object:");
            console.error(errorMessage);


        }


    }
});

这篇关于返回JavaScript代码时如何在PHP / Dojo中正确生成异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆