I have 2 functions which are dependent on each other. func1 is a method returning a value from database. If there is an error executing func1, an alert box shows and I dont want to execute func2. If func1 executes successfully without an error, then only I want func2 to get executed. I dont know how to achieve this. Any help will be greatly appreciated. Thank you in advance.
Regards,
Kevin.
Perhaps I'm missing something, but isn't as simple as:
private function getData():void
{
//get data
if (data)
{
onDataLoad();
}
else
{
//alert();
}
}
private function onDataLoad():void
{
//do something
}
Or, if your data load function returns a boolean, just work it into a similar scenario.
the function func1 should throw an error (A) or return an error code / null pointer (B).
(A)
try {
func1();
func2(); // only executed if func1 does not throw any errors
} catch (e:Error) {
// error handling
}
(B)
var myData:Object = func1();
if(myData != null) {
func2();
}
Related
I have written an async Flutter/Dart function which behaves unexpectedly in my opinion. Following code structure:
static Future<bool> verifySometing() async {
try {
await getCloudData().then((snapshot) {
if (snapshot.exists && snapshot.hasData) {
bool dataValid = await validateData(snapshot.data);
if (dataValid) {
print('Data is correct');
return true;
}
}
});
} catch (e) {
print('Error $e');
return false;
}
print('Something went wrong');
return false;
}
The expected result would be that the function awaits the cloud data, then awaits validation and returns true if the data is valid. In this case, the console would show the following and the function would return true:
Data is correct
What happens in practice is that the console shows the following output and the function first returns true and then false:
Data is correct
Something went wrong
This goes against anything I thought to know about funtions in Dart because I always assumed that once return is fired, the function is done. Any ideas how this happens?
The issue is with this line.
await getCloudData().then((snapshot) {
Here, instead of just awaiting, you have also attached a then callback. So in actuality, whatever you are returning is return value of the callback function ie., (snapshot) {}.
The callback function that you need to pass into the then takes that return true and gives it to us as the result of await.
So, if you would've put something like
var bool = await getCloudData().then((snapshot) { ..... });
Then this bool, would've been equal to true. That's it. No return from the your main function.
Change it to this,
var snapshot = await getCloudData();
if (snapshot.exists && snapshot.hasData) {
bool dataValid = await validateData(snapshot.data);
if (dataValid) {
print('Data is correct');
return true;
}
}
Hope, I was able to explain clearly.
There are a few of faults in your assumptions.
First, you've attached a then to the future returned by getCloudData(). This means that you aren't awaiting getCloudData(), but instead the additional future returned by getCloudData().then(...), and that future will return when the callback function passed to it completes. (And unless the first future throws an error, the callback will be called.)
Second, the callback function operates on its own scope. So this code is not doing what you think it's doing:
bool dataValid = await validateData(snapshot.data);
if (dataValid) {
print('Data is correct');
return true;
}
This return will affect the callback function, not the verifySomething function.
Given these, the order of operation is as follows:
The validateSomething function awaits getCloudData().then(...).
getCloudData() gets called.
getCloudData() returns, the callback passed to then is called.
(Assuming the snapshot has data) validateData is called.
(Assuming data is successfully validated) "Data is correct" gets printed and the callback function returns true.
validateSomething is notified that the awaited future is complete, so execution resumes.
"Something went wrong" gets printed and the validateSomething function returns false.
Generally speaking, these kinds of errors are common when mixing async/await and then patterns. Unless you know what you're doing, stick with either one or the other, preferably the async/await pattern. For example, a refactor of your code to eliminate the call to then is as follows:
static Future<bool> verifySometing() async {
try {
final snapshot = await getCloudData();
if (snapshot.exists && snapshot.hasData) {
bool dataValid = await validateData(snapshot.data);
if (dataValid) {
print('Data is correct');
return true;
}
}
} catch (e) {
print('Error $e');
return false;
}
print('Something went wrong');
return false;
}
Now that there isn't a pesky closure to deal with, return will return from validateSomething as expected and you don't need to deal with issues like callbacks and scope.
I have created a 'Hello World' type test suite, but I can't seem to have it run any tests. When executed, it simply says:
reached run function
Process finished with exit code 0
I can thus tell that my two functions containing tests are never executed, as they contain print statements that are never printed.
This is the source code of my tests/run.ceylon file:
import ceylon.test {
TestRunner, createTestRunner
}
Anything myTests1 () {
// assert something true!
assert(40 + 2 == 42);
print("myTests1");
return null;
}
void myTests2 () {
// assert something false!
assert(2 + 2 == 54);
print("myTests2");
}
"Run the module `tests`."
shared void run() {
print("reached run function");
TestRunner myTestRunner = createTestRunner(
[`function myTests1`, `function myTests2`]);
myTestRunner.run();
}
the test function has to be annotated with test annotation, see https://modules.ceylon-lang.org/repo/1/ceylon/test/1.3.3.1/module-doc/api/index.html#start
What's the most performant way to parse JSON in Node.js?
What's the advantage of using process.nextTick and slightly delaying the answer in the following snippet and shouldn't the whole try/catch be encapsulated into process.nextTick?
function parseJSON(json, done) {
try {
var result = JSON.parse(json);
process.nextTick(function() { done(null, result); });
} catch (err) {
process.nextTick(function() { done(err); });
}
}
First, because JSON.parse is synchronous, there's no point in using a callback.
These two blocks of code essentially do the same thing. The bottom one is more efficient:
parseJSON(json, function(err, result) {
if (err) {
//ERROR
}
else {
//PARSED
}
});
vs
try {
var result = JSON.parse(json);
//PARSED
}
catch (e) {
//ERROR
}
Now onto your actual question(s):
What's the advantage of using process.nextTick...
Basically there is no "advantage" except that if you don't use process.nextTick then your function call becomes more synchronous. Take this example for instance:
console.log('1');
parseJSON(json, function(err, result) {
console.log('parsed');
});
console.log('2');
When using process.nextTick you'll get this output:
1
2
parsed
This happens because process.nextTick puts the callback function at the end of the event loop. Meaning it'll let other things happen first then execute the callback.
If you didn't use process.nextTick then you'd get this output:
1
parsed
2
This happens because parseJSON won't exit until the callback is called.
Both versions are valid, but with callbacks you usually to want them to be truly asynchronous.
As for the try-catch, it's fine where it's at if you're trying to catch errors coming from JSON.parse. Since you appear to want to handle the errors (because you're passing the error parameter to the callback if it throws an exception) then I'd say it's correct as is.
First of all
. process.nextick is async... Try catch may not work as you expext.. JSON.parse is preferred way to parse json string
--> What's the most performant way to parse JSON in Node.js?
JSON stream probably, becasue of the low memory footprint.
See the work done by dominictarr or mafintosh
https://github.com/mafintosh/json-format-stream
https://github.com/mafintosh/through-json
https://github.com/dominictarr/JSONStream
Api Call
http://localhost:8888/api/v1/users/100 //doesn't exist
Html Call
http://localhost:8888/admin/users/100 //doesn't exist
Obviously, I don't want the Html Call exception to return json data and I don't want the Api Call to return Html Data.
I am not exception handling in the controller. I am exception handling in my UserRepository. As such, my controllers are just returning a result from the user repository.
class Sentry2UserRepository implements UserInterface {
public function findById($id) {
try {
return Sentry::findUserById($id);
}
catch (\Cartalyst\Sentry\Users\UserNotFoundException $e) {
// Do something here
return false;
}
}
}
Question 1: What is the normal / proper way of passing an error back to controller so that it will know what to display?
Question 2: Is there a standard json API format for exceptions / errors?
Question 3: Is it good practice for a Web UI to consume an internal JsonApi? Or am I doing things the right way at the moment with my WebUi controllers Querying the same Repositories as the Api?
Try this magic in your filters.php:
App::error(function(Exception $exception, $httpCode)
{
if (Request::is('api/*')){
return Response::json( ['code' => $exception->getCode(), 'error' => $exception->getMessage()], $httpCode );
}else{
$layout = View::make('layouts.main');
$layout->content = View::make('errors.error')->with('code', $exception->getCode())->with('error', $exception->getMessage())->with('httpCode',$httpCode);
return Response::make($layout, $httpCode);
}
});
First of all, I think your approach in Sentry2UserRepository is not bad, it's ok, IMO.
Question 1: What is the normal / proper way of passing an error back
to controller so that it will know what to display?
Well, IMO, depending on the application you should determine how you should handle exceptions. You mentioned so that it will know what to display and in this case it depends on how and what information you need from an exception to take the next action after an exception occured. now if you need the error message then you may return the return $e->getMessage() so you'll exactly know what actually happened. There are many ways to do this, for example, using a single catch :
try{
// ...
}
catch( Exception $e )
{
if ($e instanceof UserNotFoundException) {
// it's an instance of UserNotFoundException, return accordingly
}
elseif ($e instanceof SomethinElseException) {
// it's an instance of SomethinElseException, return accordingly
}
}
Also, you can use different custom exception classes and may use multiple catch blocks, i.e.
class AnException extends Exception
{
public function customErrorMessage()
{
return `AnException occurred!`
}
}
class AnotherException extends Exception
{
public function customErrorMessage()
{
return `AnotherException occurred!`
}
}
Then catch using multiple catch blocks, i.e.
try
{
// ...
}
catch(AnException $e)
{
return $e->customErrorMessage();
}
catch(AnotherException $e)
{
return $e->customErrorMessage();
}
catch(Exception $e)
{
return $e->getMessage();
}
Question 2: Is there a standard json API format for exceptions / errors?
Question 3: Is it good practice for a Web UI to consume an internal JsonApi? Or am I doing things the right way at the moment with my WebUi controllers Querying the same Repositories as the Api?
Actually I don't know about such an api and you are doing right, IMO. It's because, you have this
class Sentry2UserRepository implements UserInterface {
public function findById($id) {
try {
return Sentry::findUserById($id);
}
catch (\Cartalyst\Sentry\Users\UserNotFoundException $e) {
// Do something here
return false;
}
}
}
So, it's possible to write code in controller something like this
if(findById(5)) {
// found and dump it to the view
}
else {
// show "Not Found !", false will be back only for UserNotFoundException
}
But, if you had this in your UserNotFoundException catch
return $e; // or anything else (maybe an array containing status and message)
Then It's not possible to write this simple code
if(findById(5)) {
// found and dump it to the view
}
Because, is statement will be true for $e object oe for an array, so you have to check it again, using somrthing like this
$result = findById(5);
if($result && $result->code && $result->code === 0) {
// something according to code
}
Or maybe, something like this
if($result && $result->code) {
// error happened, now determine the code
switch($result->code){
case 0:
// show message
break;
case 1:
// show message
break;
}
}
So, IMO, why, you need to show the user, what error happened in your application, why not just to states, either you got data or you didn't get it. isn't it simple ? Just KISS. This is my opinion only, that's it.
In web app development I would like a consistent way to catch and report error conditions. For example, a database update routine may detect a variety of error conditions and ideally I would like the application to capture them and report gracefully. The code below din't work because retdiag is undefined when error is thrown...
function saveData(app,e) {
var db ;
var retdiag = "";
var lock = LockService.getPublicLock();
lock.waitLock(30000);
try {
// e.parameters has all the data fields from form
// re obtain the data to be updated
db = databaseLib.getDb();
var result = db.query({table: 'serviceUser',"idx":e.parameter.id});
if (result.getSize() !== 1) {
throw ("DB error - service user " + e.parameter.id);
}
//should be one & only one
retdiag = 'Save Data Finished Ok';
}
catch (ex) {
retdiag= ex.message // undefined!
}
finally {
lock.releaseLock();
return retdiag;
}
}
Is there a good or best practice for this is GAS?
To have a full error object, with message and stacktrace you have to build one, and not just throw a string. e.g. throw new Error("DB error ...");
Now, a more "consistent" way I usually implement is to wrap all my client-side calls into a function that will treat any errors for me. e.g.
function wrapper_(f,args) {
try {
return f.apply(this,args);
} catch(err) {
;//log error here or send an email to yourself, etc
throw err.message || err; //re-throw the message, so the client-side knows an error happend
}
}
//real client side called functions get wrapped like this (just examples)
function fileSelected(file,type) { return wrapper_(fileSelected_,[file,type]); }
function loadSettings(id) { return wrapper_(loadSettings_,[id]); }
function fileSelected_(file,type) {
; //do your thing
}
function loadSettings_(id) {
; //just examples
throw new Error("DB error ...");
}