我可以使用.Last.value
2 + 2
## [1] 4
.Last.value
## [1] 4
我可以使用last.warning
访问最新警告。
warning("!!!")
## Warning message:
## !!!
last.warning
## $`!!!`
## NULL
我可以使用geterrmessage()
stop("!!!")
## Error: !!!
geterrmessage()
## [1] "Error: !!!\n"
如果我事先知道可能会抛出错误,我可以使用tryCatch
返回错误对象。
tryCatch(stop("!!!"), error = identity)
## <simpleError in doTryCatch(return(expr), name, parentenv, handler): !!!>
如何在抛出之后将最后一个错误检索为对象?
例如,如果我输入
stop("!!!")
然后我希望能够输入getlasterror()
或类似内容并检索simpleError
个对象。
答案 0 :(得分:2)
如果您是代码的作者,解决此问题的现代方法是使用abort()
包。您使用last_error()
抛出错误,然后使用library(rlang)
f <- function() {
abort("@@@")
}
f()
## Error: @@@
last_error()
## <error>
## message: @@@
## class: `rlang_error`
## backtrace:
## ─base::withCallingHandlers(...)
## ─global::f()
## Call `summary(rlang::last_error())` to see the full backtrace
g <- function() {
msg <- "###"
abort(msg)
}
g()
## Error: ###
last_error()
## <error>
## message: ###
## class: `rlang_error`
## backtrace:
## ─base::withCallingHandlers(...)
## ─global::g()
## Call `summary(rlang::last_error())` to see the full backtrace
h <- function() {
err_fn <- abort
err_fn("$$$")
}
h()
## Error: $$$
last_error()
## <error>
## message: $$$
## class: `rlang_error`
## backtrace:
## ─base::withCallingHandlers(...)
## ─global::h()
## Call `summary(rlang::last_error())` to see the full backtrace
检索最后一个错误。
stop()
这方面的局限性在于它不能处理由tryCatch()
生成的错误。
根据David Arenburg的评论,您可以将get_last_error <- function()
{
tr <- .traceback()
if(length(tr) == 0)
{
return(NULL)
}
tryCatch(eval(parse(text = tr[[1]])), error = identity)
}
与追溯结合使用。
# before an error is thrown
get_last_error()
## NULL
# after an error at the top level
stop("!!!")
## Error: !!!
get_last_error()
## <simpleError in eval(expr, envir, enclos): !!!>
# after an error inside a function
f <- function() stop("@@@")
f()
## Error in f() : @@@
get_last_error()
## <simpleError in eval(expr, envir, enclos): @@@>
示例:
g <- function()
{
msg <- "###"
stop(msg)
}
g()
## Error in g() : ###
get_last_error()
## <simpleError in stop(msg): object 'msg' not found>
h <- function()
{
err_fn <- stop
err_fn("$$$")
}
h()
## Error in h() : $$$
get_last_error()
## <simpleError in eval(expr, envir, enclos): could not find function "err_fn">
限制:
当您重新评估错误代码时,所有变量都需要可用。因此,以下示例不起作用,例如:
options(error = dump.frames)
通过设置last.dump
,错误发生时的调用堆栈存储在全局环境中名为last.dump[length(last.dump)]
的变量中。环境debugger(last.dump)
有时包含错误对象,有时包含会产生错误的参数。
<!DOCTYPE html>
<html>
<head>
<title>EasyUI Drag-n-Drop Test</title>
<style>
body, html {
width: 100%;
height: 100%;
overflow: hidden;
padding: 3px;
box-sizing: border-box;
margin: 0;
}
</style>
<!-- Load JQuery -->
<script type="text/javascript" src="https://code.jquery.com/jquery-2.2.3.min.js"></script>
<!-- Load EasyUI Framework -->
<script type="text/javascript" src="http://www.jeasyui.com/easyui/jquery.easyui.min.js"></script>
<link rel="stylesheet" type="text/css" href="http://www.jeasyui.com/easyui/themes/default/easyui.css">
<link rel="stylesheet" type="text/css" href="http://www.jeasyui.com/easyui/themes/icon.css">
<!-- Load Other Javascript Modules -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.6.1/fabric.min.js"></script>
<!-- Direct / Inline Javascript for this Document -->
<script type="text/javascript">
// Handle Tree & Canvas Drag & Drop Events
function handleStartDrag(e) {
console.log('handleStartDrag');
console.table(e);
var data = e.dataTransfer.getData('text');
alert('Drag-n-Dropped ['+text+']');
return false;
};
function handleStopDrag(e) {
console.log('handleStopDrag');
console.table(e);
return false;
};
function handleDragEnter(e) {
console.log('handleDragEnter');
console.table(e);
return false;
};
function handleDragOver(e) {
console.log('handleDragOver');
console.table(e);
return false;
};
function handleDragLeave(e) {
console.log('handleDragLeave');
console.table(e);
return false;
};
function handleDrop(e) {
console.log('handleDrop');
console.table(e);
var data = e.dataTransfer.getData('text');
alert('Drag-n-Dropped ['+text+']');
return false;
};
function loadFilter(data) {
var nodes = [];
for(var i = 0; i < data.length; i++) {
var node = data[i];
nodes.push({
id: node.id,
text: node.name,
attributes: node,
});
}
return nodes;
};
function loadPropertyGrid(node) {
node = node || {id: '', text: '', attributes: {id: '', name: '', address: '', city: '', state: '', zip: '', phone: ''}};
$('#pg').propertygrid('loadData', [
{name: "ID", value: node.attributes.id, group: "", editor: 'text'},
{name: "Name", value: node.attributes.name, group: "", editor: 'text'},
{name: "Address", value: node.attributes.address, group: "", editor: 'text'},
{name: "City", value: node.attributes.city, group: "", editor: 'text'},
{name: "State", value: node.attributes.state, group: "", editor: 'text'},
{name: "Zip", value: node.attributes.zip, group: "", editor: 'text'},
{name: "Phone", value: node.attributes.phone, group: "", editor: 'text'},
]);
$('#pg').propertygrid('fitColumns');
};
function getData() {
return [
{id: 1, name: "Tom Jones", address: "123 Blah Lane", city: "Somewhereville", state: "XY", zip: "12345", phone: "123-456-7890"},
{id: 2, name: "Sally Sue", address: "162 Foobar Dr", city: "Blechtown", state: "QZ", zip: "98672", phone: "345-123-5432"},
{id: 3, name: "Ralph Slug", address: "1762 Uknow St", city: "Mumbleville", state: "WE", zip: "21763", phone: "828-462-1786"}, ];
};
function getPgColumns() {
return [[
{field: 'name', title: 'Item', width: 30, sortable: true, resizeable: true},
{field: 'value', title: 'Value', width: 70, resizeable: true},
]];
}
//-----------------------------------------------------------------
$(document).ready(function() {
// Set up Fabric.Js Canvas
var canvas = new fabric.Canvas('cv');
var gridWidth = 1000; // define canvas grid width
var gridHeight= 1000; // define canvas grid height
canvas.clear(); // Clear (remove) all objects off the canvase
setSelectionStyle(); // Set canvase selection style
drawGrid(gridWidth, gridHeight, 20); // Draw a grid on the canvas
// Bind the event listeners for the canvas
var canvasWrapper = document.getElementById('cv_wrapper');
canvasWrapper.addEventListener('startdrag', handleStartDrag, false);
canvasWrapper.addEventListener('stopdrag', handleStopDrag, false);
canvasWrapper.addEventListener('dragenter', handleDragEnter, false);
canvasWrapper.addEventListener('dragover', handleDragOver, false);
canvasWrapper.addEventListener('dragleave', handleDragLeave, false);
canvasWrapper.addEventListener('drop', handleDrop, false);
// Draw something on the canvas
var grp = new fabric.Group([]);
var r1 = new fabric.Rect({left: 0, top: 0, width: 50, height: 50, fill: '#f00'});
var r2 = new fabric.Rect({left: 25, top: 25, width: 50, height: 50, fill: '#00f'});
grp.addWithUpdate(r1);
grp.addWithUpdate(r2);
canvas.add(grp);
canvas.renderAll();
loadPropertyGrid();
function setSelectionStyle() {
canvas.selectionColor = 'rgba(0,255,0,0.3)';
canvas.selectionBorderColor = '#f33';
canvas.selectionLineWidth = 2;
};
function drawGrid(gridWidth, gridHeight, gridSize) {
// to manipulate grid after creation
var grid = new fabric.Group([], {
left: 0,
top: 0,
lockRotation: true,
lockScalingX: true,
lockScalingY: true,
hasControls: false,
hasBorders: false,
hasRotatingPoint: false,
lockMovementX: true,
lockMovementY: true,
selectable: false,
});
// define presentation option of grid
var lineOption = {stroke: 'rgba(0,0,0,.4)', strokeWidth: 1, selectable:false, strokeDashArray: [3, 3]};
// vertical lines
for(var i = Math.ceil(gridWidth/gridSize); i--;){
grid.add( new fabric.Line([gridSize*i, 0, gridSize*i, gridHeight], lineOption) );
}
// horizontal lines
for(var i = Math.ceil(gridHeight/gridSize); i--;){
grid.add( new fabric.Line([0, gridSize*i, gridWidth, gridSize*i], lineOption) );
}
// add group to canvas
canvas.add(grid);
};
});
</script>
</head>
<body>
<div class="easyui-layout" style="width:100%;height:100%;">
<!-- WEST (LEFT SIDE) -->
<div data-options="region:'west',split:true" title="EasyUI Tree Widget" style="width:240px;overflow:hidden">
<div class="easyui-layout" style="width:100%;height:100%">
<div data-options="region:'north',split:true" style="height:60%">
<!-- Network Device Tree -->
<ul class="easyui-tree" data-options="
data: getData(),
loadFilter: function(data) { return loadFilter(data); },
onClick: function(node){ loadPropertyGrid(node); },
dnd: true,
onDragEnter: function(e){ handleDragEnter(e); },
onDragOver: function(e) { handleDragOver(e); },
onDragLeave: function(e) { handleDragLeave(e); },
onDrop: function(e) { handleDrop(e); },
"></ul>
</div>
<div data-options="region:'center'" title="EasyUI PropertyGrid" style="height:40%">
<!-- Property Grid -->
<table id="pg" class="easyui-propertygrid" style="width:100%" data-options="
method:'get',
showGroup:false,
scrollbarSize:0,
columns: getPgColumns(),
">
</table>
</div>
</div>
</div>
<!-- CENTER -->
<div data-options="region:'center',title:'Fabric.js Canvas',iconCls:'icon-ok'">
<div data-container="FabricCanvas" id="cv_wrapper">
<canvas id="cv" class="canvas-container" width="1000" height="1000"></canvas>
</div>
</div>
</body>
</html>
允许对堆栈进行交互式事后探索,作为获取错误对象的替代方法。