Как правильно генерировать исключения в PHP / Dojo при возврате кода javascript

Мне трудно понять, как обрабатываются исключения, когда динамически динамически вводится код через AJAX и выполняется через eval . С клиентским javascript это довольно просто, если у меня есть код, такой как этот

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

это вызовет исключение, потому что propA , который имеет тип undefined , не имеет x . Кроме того, поднятое исключение очень легко понять.

Теперь давайте разместим вышеуказанный код в текстовом файле, позвоним ему test.js и сохраним его на сервере. Теперь давайте загрузим его динамически с помощью Ajax. Я использую следующий код, чтобы загрузить его динамически

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

Вот очень простой php-скрипт для загрузки файла и возврата его в виде javascript-кода

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

В приведенном выше вызове dojo.xhrGet свойство error можно установить на функцию для отображения сообщения об ошибке, вот пример некоторых из многих способов, которыми это можно сделать.

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

Ниже приведен пример вывода. Хотя этот вывод для другой проблемы, он подчеркивает, насколько непостижимо это:

 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 ?


Вот несколько схожий вопрос.


Фикин дал хорошее решение этой проблемы ниже, поэтому я дал ему щедрость. Используя его решение, я получил результат, который выглядел примерно так (я немного сократил его)

  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 BG 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 -  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 BG 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 -  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 BG 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 -  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 BG 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 -  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 BG 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 

Единственное, чего мне не хватает, что мне нужно, это возможность указать, в какой строке возникла проблема.

Ниже приведен фрагмент, который обнаруживает ошибки, не связанные с сетью, из запроса xhr-get и выводит некоторую информацию об этом в консоли.

Существует дополнительная функция isEvalError (), которая проходит через все типы ошибок eval … которые я не очень горжусь. Лучше всего было бы получить родительский объект подклассов errorMessage. Я думаю, что вы можете вырезать isEvalError () вообще, потому что в этом блоке не должно быть никакой другой ошибки.

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

Это действительно зависит от того, что вы имеете в виду «продуктивный способ справиться с исключениями». Если все, что вам нужно сделать, это просмотреть содержимое исключения, просто

 console.log(errorMessage); 

позволит вам легко проверить объект ошибки в приличном браузере, таком как Chrome или Firefox (с Firebug). (Вместо того, чтобы заставлять вас делать тонну команд console.log)

Досадная вещь об исключениях Dojo внутри асинхронного кода заключается в том, что они всегда пойманы и обрабатываются, поэтому большинство отладчиков браузера игнорируют их. Заметным исключением из этого правила является Chrome, где вы можете сказать отладчику приостановить все исключения.


BTW: Я не вижу, как в этом случае Javascript-исключения и Dojo имеют какое-то отношение к PHP, поскольку они происходят на стороне клиента, и сервер ничего не может с ними поделать. Кроме того, что, черт возьми, вы делаете, отправив код Javascript в AJAX? Большую часть времени клиент выполняет запрос, который будет использоваться для данных , в виде обычного текста, JSON или XML.