How to Drag and Drop File Upload with HTML CSS JavaScript

In this article you will know how to create Drag and Drop File Upload using HTML CSS and JavaScript. Earlier I have shared many more types of Drag and Drop elements and File Upload and Preview section. This is basically a drag and drop multiple file upload that I made with javascript.

Drag and Drop File Upload with JavaScript

Now it’s time to create JavaScript Drag and Drop File Upload. Here I have created the basic structure by html. I designed it with css and activated this Drag & Drop or Browse – File upload with javascript.

Drag And Drop File Upload Javascript

Drag and drop file upload in JavaScript refers to the ability to select one or more files using the drag and drop gesture, and then upload those files to a server. 

This feature is typically implemented using JavaScript event listeners, such as “dragover” and “drop,” that detect when a file is being dragged over a specific element on the page and when the file is dropped onto that element. Within this project () you can upload the image by selecting it and you can also upload it by drag and drop. Also here you can upload multiple images.

As you can see above this is a simple javascript drag and drop file upload project. Here I have created a small area or box. Inside that box is a button. You can select the image by clicking on that button or you can drag and drop the image into the box. Then the uploaded image can be seen in the preview box below.

How To Make A Drag and Drop File Uploader With JavaScript

Now if you want to build(How To Make A Drag-and-Drop File Uploader With javascript) this project then follow the step by step tutorial below. Here I have given you the necessary explanation and source code. A bit more JavaScript is used here. But there is no reason to worry. I have explained each code step by step and tried to explain you completely why I used that line of code.

Besides, I have given a preview after each step. Which will help you to know what kind of result will be seen after using that code.

Step 1: Basic Structure of Drag and Drop File Uploader

I have created the basic structure of this Drag and drop multiple file upload using the following html and css. All the information of that box can be seen. I used white for the background color of the box and some shadows around it.

<div class="container">

</div>
* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
  font-family: "Poppins", sans-serif;
}
body {
  background-color: #a4b7e3;
}
.container {
  background-color: #ffffff;
  width: 60%;
  min-width: 27.5em;
  padding: 3.12em 1.87em;
  position: absolute;
  transform: translate(-50%, -50%);
  left: 50%;
  top: 50%;
  box-shadow: 0 1.25em 3.43em rgba(0, 0, 0, 0.08);
  border-radius: 0.5em;
}

Basic Structure of Drag and Drop File Uploader

Step 2: Create a file upload button

Now an input button is created to upload the file. I have created this button using HTML’s input function. For uploading image only I used accept=”image/*” which basically will help to upload image file only.

<input type="file" id="upload-button" multiple accept="image/*" />
<label for="upload-button">
  <i class="fa-solid fa-upload"></i>&nbsp; Choose Or Drop Photos
</label>
input[type="file"] {
  display: none;
}
label {
  display: block;
  position: relative;
  background-color: #025bee;
  color: #ffffff;
  font-size: 1.1em;
  text-align: center;
  width: 16em;
  padding: 1em 0;
  border-radius: 0.3em;
  margin: 0 auto 1em auto;
  cursor: pointer;
}

Create a file upload button

Step 3: Create a place to preview the image

Now an area is created, in which the images can be viewed i.e. image preview area is created. How images are displayed is determined by css.

<div id="error"></div>
<div id="image-display"></div>
#image-display {
  position: relative;
  width: 90%;
  margin: 0 auto;
  display: flex;
  justify-content: space-evenly;
  gap: 1.25em;
  flex-wrap: wrap;
}
#image-display figure {
  width: 45%;
}
#image-display img {
  width: 100%;
}
#image-display figcaption {
  font-size: 0.8em;
  text-align: center;
  color: #5a5861;
}
.active {
  border: 0.2em dashed #025bee;
}
#error {
  text-align: center;
  color: #ff3030;
}

Step 4: Enable the drag and drop multiple files uploader

Now it’s time to implement this drag and drop multiple file uploader using javascript. Here I have given the necessary explanation, hope you will not have any difficulty in understanding.

These lines of code are assigning variables to different elements on a webpage by their ID to active Drag And Drop File Uploader in javascript. The variables are:

  • uploadButton is assigned to the element with the ID “upload-button”
  • chosenImage is assigned to the element with the ID “chosen-image”
  • fileName is assigned to the element with the ID “file-name”
  • container is assigned to the first element with the class “container”
  • error is assigned to the element with the ID “error”
  • imageDisplay is assigned to the element with the ID “image-display”

It appears that these variables will be used to manipulate these elements and their properties in later JavaScript code.

let uploadButton = document.getElementById("upload-button");
let chosenImage = document.getElementById("chosen-image");
let fileName = document.getElementById("file-name");
let container = document.querySelector(".container");
let error = document.getElementById("error");
let imageDisplay = document.getElementById("image-display");

This code defines a function fileHandler() that takes in three parameters: file, name, and type. The function checks if the file is of type image by checking the first part of the type string before “/” if it is not of type image it sets the innerText of the error element to “Please upload an image file” and returns false. 

If the file is an image, it sets the innerText of the error element to an empty string and creates a new FileReader object, which reads the contents of the file as a Data URL. 

When the file has been read, the onloadend event is triggered, at this point it creates an imageContainer element and an img element, sets the source of the img element to the result of the file reader, appends the img element to the imageContainer element, and then appends a figcaption element containing the file name to the imageContainer element. Finally, it appends the imageContainer element to the imageDisplay element.

const fileHandler = (file, name, type) => {
  if (type.split("/")[0] !== "image") {
    //File Type Error
    error.innerText = "Please upload an image file";
    return false;
  }
  error.innerText = "";
  let reader = new FileReader();
  reader.readAsDataURL(file);
  reader.onloadend = () => {
    //image and file name
    let imageContainer = document.createElement("figure");
    let img = document.createElement("img");
    img.src = reader.result;
    imageContainer.appendChild(img);
    imageContainer.innerHTML += `<figcaption>${name}</figcaption>`;
    imageDisplay.appendChild(imageContainer);
  };
};

Now Drag and Drop File Upload project upload button should be activated. This code attaches an event listener to the uploadButton element that listens for a “change” event. When the event is fired, the function inside the event listener is executed. The function clears the content of the imageDisplay element by setting its innerHTML to an empty string. 

Then it creates an array of the files from the uploadButton element, and for each file in that array, it calls the fileHandler() function and passes in the file, the file.name, and the file.type as the arguments. 

This code is used to handle the event of a user selecting and uploading one or more image files, displaying each image file and its name on the page by calling the fileHandler function for each file.

//Upload Button
uploadButton.addEventListener("change", () => {
  imageDisplay.innerHTML = "";
  Array.from(uploadButton.files).forEach((file) => {
    fileHandler(file, file.name, file.type);
  });
});

Now you need to define what happens when you drag the file into the Simple javascript Drag and Drop File Upload box. This code attaches an event listener to the container element that listens for a “dragenter” event. When the event is fired, the function inside the event listener is executed. The function calls preventDefault() and stopPropagation() on the event object (e) to prevent the default browser behavior and stop the event from propagating. 

Then it adds a class “active” to the container element’s classList. This code is probably used to handle the event of a user dragging an item over the container element, indicating that the container is a valid drop target. 

The class “active” is added to the container which can be used to style it and give visual feedback that the container is active and ready to accept the dragged item.

container.addEventListener(
  "dragenter",
  (e) => {
    e.preventDefault();
    e.stopPropagation();
    container.classList.add("active");
  },
  false
);

Now you need to determine what happens if you drag leave within the HTML drag drop upload area. This code attaches an event listener to the container element that listens for a “dragleave” event. When the event is fired, the function inside the event listener is executed. The function calls preventDefault() and stopPropagation() on the event object (e) to prevent the default browser behavior and stop the event from propagating. 

Then it removes the class “active” from the container element’s classList. This code is probably used to handle the event of a user dragging an item out of the container element, indicating that the container is no longer a valid drop target. 

The class “active” is removed from the container, it can be used to style it and give visual feedback that the container is no longer active and no longer ready to accept the dragged item.

container.addEventListener(
  "dragleave",
  (e) => {
    e.preventDefault();
    e.stopPropagation();
    container.classList.remove("active");
  },
  false
);

Upload files with Drag and Drop to determine what happens when dragover. This code attaches an event listener to the container element that listens for a “dragover” event. When the event is fired, the function inside the event listener is executed. The function calls preventDefault() and stopPropagation() on the event object (e) to prevent the default browser behavior and stop the event from propagating. 

container.addEventListener(
  "dragover",
  (e) => {
    e.preventDefault();
    e.stopPropagation();
    container.classList.add("active");
  },
  false
);

This code attaches an event listener to the container element that listens for a “drop” event. When the event is fired, the function inside the event listener is executed. The function calls preventDefault() and stopPropagation() on the event object (e) to prevent the default browser behavior and stop the event from propagating. 

Then it removes the class “active” from the container element’s classList. It then creates a variable draggedData which holds the dataTransfer object of the event, which contains the data that was dropped onto the element. It then creates a variable files which holds the file object from the draggedData object. It clears the content of the imageDisplay element by setting its innerHTML to an empty string. 

Then it creates an array of the files and for each file in that array, it calls the fileHandler() function and passes in the file, the file.name, and the file.type as the arguments. This code is used to handle the event of a user dropping one or more files on to the container element, which then calls the fileHandler function to display the image and its name on the page.

container.addEventListener(
  "drop",
  (e) => {
    e.preventDefault();
    e.stopPropagation();
    container.classList.remove("active");
    let draggedData = e.dataTransfer;
    let files = draggedData.files;
    imageDisplay.innerHTML = "";
    Array.from(files).forEach((file) => {
      fileHandler(file, file.name, file.type);
    });
  },
  false
);

Now it is determined that every time the page is loaded all the information contained in the Drag and Drop File Upload with HTML CSS JavaScript will be removed. This code assigns an anonymous function to the onload property of the window object, which is fired when the page has finished loading. The function sets the innerText of the error element to an empty string, effectively clearing any pre-existing text. 

window.onload = () => {
  error.innerText = "";
};

Drag and Drop File Upload with JavaScript

Hope you got to know from above tutorial how I created this project(Drag and Drop File Upload Using HTML,CSS & JavaScript). I have already shared many more JavaScript tutorials with you.

Be sure to comment how you liked this Drag and Drop File Upload JavaScript tutorial.

Original article source at: https://foolishdeveloper.com/

#javascript #html #css #drop #upload 

How to Drag and Drop File Upload with HTML CSS JavaScript
Desmond  Gerber

Desmond Gerber

1675479180

Python TypeError

In Python, items of iterable objects such as lists, tuples, or strings can be accessed by using their index numbers.

The index number starts from 0 and increases by 1 for each subsequent item in the object.

For example, here’s how to access the first character in a string:

# Declare a string variable
my_str = "Good Morning!"

# Print the first character in the string
print(my_str[0])  # G

The code above will print G because it’s the first character of the string my_str.

The error TypeError: string indices must be integers occurs when you try to access a character in a string using a string.

For example, suppose you try to access the first character as follows:

my_str = "Good Morning!"

print(my_str['G'])  # ❌

Output:

Traceback (most recent call last):
  File ...
    print(my_str['a'])
TypeError: string indices must be integers

To fix this error, make sure you’re passing an integer inside the square brackets.

The following three scenarios may cause this error:

  1. Slicing a string with a wrong syntax
  2. Accessing a dictionary in a wrong way
  3. Accessing a JSON string like a JSON object

The following examples show how to fix this error in each scenario

1. Slicing a string with a wrong syntax

Aside from passing the index number of a character, you can also extract several characters from a string by using the slicing syntax.

The slicing syntax is as follows:

string_object[start_index:end_index]

The start_index is the starting position of the slice and end_index is the ending position of the slice. The two are separated using a colon (:) operator.

When start_index is not specified, it is assumed to be 0. If end_index is not specified, it is assumed to be the length of the string itself.

The start_index is included in the output, but the end_index is excluded.

Here are some examples of slicing a string in Python:

my_str = "Good Morning!"

# return 'Morning'
print(my_str[5:12])

# return 'Good'
print(my_str[:4])

# return 'ood'
print(my_str[1:4])

# return 'ning!'
print(my_str[8:])

But when you pass a wrong slice syntax, then Python will give you a TypeError:

my_str = "Good Morning!"

# ❌ Use a comma to separate the integers
print(my_str[5,12])

# ❌ Use a dot to separate the integers
print(my_str[5.12])

# ❌ Use a colon but enclosed in quotes
print(my_str['5:12'])

To avoid the error, make sure that the slice syntax has the correct format.

2. Accessing a dictionary in a wrong way

Suppose you have a dictionary object as shown below:

data = {
    "name": "Nathan",
    "age" : 29
}

Now let’s say you want to access the values and print them out using a for loop:

for item in data:
    print(item['name'])  # ❌

The code above will cause a TypeError because the for loop will return the dictionary key in each iteration.

Here’s the right way for accessing a dictionary with a for loop:

data = {
    "name": "Nathan",
    "age" : 29,
    "location": "Japan"
}

for item in data:
    print(item, data[item])

Output:

name Nathan
age 29
location Japan

Because the for loop returns the keys, you can use it to access the dictionary values with the square brackets notation.

3. Accessing a JSON string like a JSON object

In Python, a JSON object is similar to a dictionary object, so you can access its values using the keys.

But at times, you might mistake a string for a JSON object:

json_str = '{"name": "Nathan","age" : 29}'

print(json_str['name'])  # ❌

The json_str object is an encoded JSON string, so trying to access the name value as shown above will cause a TypeError.

To fix this, you need to import the json library and use the json.loads() method:

import json

json_str = '{"name": "Nathan","age" : 29}'

json_obj = json.loads(json_str)

print(json_obj['name'])  # Nathan
print(json_obj['age'])  # 29

The loads() method converts a JSON string into a JSON object, which enables you to access the values like a dictionary.

Keep in mind that you don’t need to call the json.dumps() method.

The dumps() method is used to convert an object to a JSON string. But you already have a string here, so there’s no need to call it 🤷🏻

Conclusion

And there you go! Now you know three common scenarios where you may cause the TypeError: string indices must be integers in Python.

This error happens whenever you try to access a string using a string and not index numbers. It can also occur when you’re working with dictionaries and JSON objects.

The steps in this article should help you resolve the error. Happy coding! ☕️

Original article source at: https://sebhastian.com/

#python #type #error 

Python TypeError
Oral  Brekke

Oral Brekke

1675373100

Python JSONDecodeError

A JSONDecodeError: Expecting value when running Python code means you are trying to decode an invalid JSON string.

This error can happen in three different cases:

Case 1: Decoding invalid JSON content Case 2: Loading an empty or invalid .json file Case 3: A request you made didn’t return a valid JSON

The following article shows how to resolve this error in each case.

1. Decoding invalid JSON content

The Python json library requires you to pass valid JSON content when calling the load() or loads() function.

Suppose you pass a string to the loads() function as follows:

data = '{"name": Nathan}'

res = json.loads(data) 

Because the loads() function expects a valid JSON string, the code above raises this error:

Traceback (most recent call last):
  File ...
    res = json.loads(data)
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

To resolve this error, you need to ensure that the JSON string you passed to the loads() function is valid.

You can use a try-except block to check if your data is a valid JSON string like this:

data = '{"name": Nathan}'

try:
    res = json.loads(data) 
    print("data is a valid JSON string")
except json.decoder.JSONDecodeError:
    print("data is not a valid JSON string")

By using a try-except block, you will be able to catch when the JSON string is invalid.

You still need to find out why an invalid JSON string is passed to the loads() function, though.

Most likely, you may have a typo somewhere in your JSON string as in the case above.

Note that the value Nathan is not enclosed in double quotes:

data = '{"name": Nathan}'  # ❌ wrong

data = '{"name": "Nathan"}' # ✅ correct

If you see this in your code, then you need to fix the data to conform to the JSON standards.

2. You’re loading an empty or invalid JSON file

Another case when this error may happen is when you load an empty .json file.

Suppose you try to load a file named data.json file with the following code:

with open("data.json", "r") as file:
    data = json.loads(file.read())

If the data.json file is empty, Python will respond with an error:

Traceback (most recent call last):
  File ...
    data = json.loads(file.read())
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

The same error also occurs if you have invalid JSON content in the file as follows:

JSON string with invalid formatJSON string with invalid format

To avoid this error, you need to make sure that the .json file you load is not empty and has valid JSON content.

You can use a try-except block in this case to catch this error:

try:
    with open("data.json", "r") as file:
        data = json.loads(file.read())
    print("file has valid JSON content")
except json.decoder.JSONDecodeError:
    print("file is empty or contain invalid JSON")

If you want to validate the source file, you can use jsonlint.com.

3. A request you made didn’t return a valid JSON

When you send an HTTP request using the requests library, you may use the .json() method from the response object to extract the JSON content:

import requests

response = requests.get('https://api.github.com')

data = response.json()
print(data)

But if the response object doesn’t contain a valid JSON encoding, then a JSONDecodeError will be raised:

Traceback (most recent call last):
  ...

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File ...
    data = response.json()
requests.exceptions.JSONDecodeError: Expecting value: line 7 column 1 (char 6)

As you can see, the requests object also has the JSONDecodeError: Expecting value message.

To resolve this error, you need to surround the call to response.json() with a try-except block as follows:

import requests

response = requests.get('https://api.github.com')

try:
    data = response.json()
    print(data)
except:
    print("Error from server: " + str(response.content))

When the except block is triggered, you will get the response content printed in a string format.

You need to inspect the print output for more insight as to why the response is not a valid JSON format.

Conclusion

In this article, we have seen how to fix the JSONDecodeError: Expecting value error when using Python.

This error can happen in three different cases: when you decode invalid JSON content, load an empty or invalid .json file, and make an HTTP request that doesn’t return a valid JSON.

By following the steps in this article, you will be able to debug and fix this error when it occurs.

Until next time, happy coding! 🙌

Original article source at: https://sebhastian.com/

#python #json #decode #error 

Python JSONDecodeError
Monty  Boehm

Monty Boehm

1675267080

Ultimate Guide to JavaScript Error Handling

This tutorial dives into JavaScript error handling so you’ll be able to throw, detect, and handle your own errors.

Expert developers expect the unexpected. If something can go wrong, it will go wrong — typically, the moment the first user accesses your new web system.

We can avoid some web application errors like so:

  • A good editor or linter can catch syntax errors.
  • Good validation can catch user input errors.
  • Robust test processes can spot logic errors.

Yet errors remain. Browsers may fail or not support an API we’re using. Servers can fail or take too long to respond. Network connectivity can fail or become unreliable. Issues may be temporary, but we can’t code our way around such problems. However, we can anticipate problems, take remedial actions, and make our application more resilient.

Showing an Error Message is the Last Resort

Ideally, users should never see error messages.

We may be able to ignore minor issues, such as a decorative image failing to load. We could address more serious problems such as Ajax data-save failures by storing data locally and uploading later. An error only becomes necessary when the user is at risk of losing data — presuming they can do something about it.

It’s therefore necessary to catch errors as they occur and determine the best action. Raising and catching errors in a JavaScript application can be daunting at first, but it’s possibly easier than you expect.

How JavaScript Processes Errors

When a JavaScript statement results in an error, it’s said to throw an exception. JavaScript creates and throws an Error object describing the error. We can see this in action in this CodePen demo. If we set the decimal places to a negative number, we’ll see an error message in the console at the bottom. (Note that we’re not embedding the CodePens in this tutorial, because you need to be able to see the console output for them to make sense.)

The result won’t update, and we’ll see a RangeError message in the console. The following function throws the error when dp is negative:

// division calculation
function divide(v1, v2, dp) {

  return (v1 / v2).toFixed(dp);

}

After throwing the error, the JavaScript interpreter checks for exception handling code. None is present in the divide() function, so it checks the calling function:

// show result of division
function showResult() {

  result.value = divide(
    parseFloat(num1.value),
    parseFloat(num2.value),
    parseFloat(dp.value)
  );

}

The interpreter repeats the process for every function on the call stack until one of these things happens:

  • it finds an exception handler
  • it reaches the top level of code (which causes the program to terminate and show an error in the console, as demonstrated in the CodePen example above)

Catching Exceptions

We can add an exception handler to the divide() function with a try…catch block:

// division calculation
function divide(v1, v2, dp) {
  try {
    return (v1 / v2).toFixed(dp);
  }
  catch(e) {
    console.log(`
      error name   : ${ e.name }
      error message: ${ e.message }
    `);
    return 'ERROR';
  }
}

This executes the code in the try {} block but, when an exception occurs, the catch {} block executes and receives the thrown error object. As before, try setting the decimal places to a negative number in this CodePen demo.

The result now shows ERROR. The console shows the error name and message, but this is output by the console.log statement and doesn’t terminate the program.

Note: this demonstration of a try...catch block is overkill for a basic function such as divide(). It’s simpler to ensure dp is zero or higher, as we’ll see below.

We can define an optional finally {} block if we require code to run when either the try or catch code executes:

function divide(v1, v2, dp) {
  try {
    return (v1 / v2).toFixed(dp);
  }
  catch(e) {
    return 'ERROR';
  }
  finally {
    console.log('done');
  }
}

The console outputs "done", whether the calculation succeeds or raises an error. A finally block typically executes actions which we’d otherwise need to repeat in both the try and the catch block — such as cancelling an API call or closing a database connection.

A try block requires either a catch block, a finally block, or both. Note that, when a finally block contains a return statement, that value becomes the return value for the whole function; other return statements in try or catch blocks are ignored.

Nested Exception Handlers

What happens if we add an exception handler to the calling showResult() function?

// show result of division
function showResult() {

  try {
    result.value = divide(
      parseFloat(num1.value),
      parseFloat(num2.value),
      parseFloat(dp.value)
    );
  }
  catch(e) {
    result.value = 'FAIL!';
  }

}

The answer is … nothing! This catch block is never reached, because the catch block in the divide() function handles the error.

However, we could programmatically throw a new Error object in divide() and optionally pass the original error in a cause property of the second argument:

function divide(v1, v2, dp) {
  try {
    return (v1 / v2).toFixed(dp);
  }
  catch(e) {
    throw new Error('ERROR', { cause: e });
  }
}

This will trigger the catch block in the calling function:

// show result of division
function showResult() {

  try {
    //...
  }
  catch(e) {
    console.log( e.message ); // ERROR
    console.log( e.cause.name ); // RangeError
    result.value = 'FAIL!';
  }

}

Standard JavaScript Error Types

When an exception occurs, JavaScript creates and throws an object describing the error using one of the following types.

SyntaxError

An error thrown by syntactically invalid code such as a missing bracket:

if condition) { // SyntaxError
  console.log('condition is true');
}

Note: languages such as C++ and Java report syntax errors during compilation. JavaScript is an interpreted language, so syntax errors aren’t identified until the code runs. Any good code editor or linter can spot syntax errors before we attempt to run code.

ReferenceError

An error thrown when accessing a non-existent variable:

function inc() {
  value++; // ReferenceError
}

Again, good code editors and linters can spot these issues.

TypeError

An error thrown when a value isn’t of an expected type, such as calling a non-existent object method:

const obj = {};
obj.missingMethod(); // TypeError

RangeError

An error thrown when a value isn’t in the set or range of allowed values. The toFixed() method used above generates this error, because it expects a value typically between 0 and 100:

const n = 123.456;
console.log( n.toFixed(-1) ); // RangeError

URIError

An error thrown by URI-handling functions such as encodeURI() and decodeURI() when they encounter malformed URIs:

const u = decodeURIComponent('%'); // URIError

EvalError

An error thrown when passing a string containing invalid JavaScript code to the eval() function:

eval('console.logg x;'); // EvalError

Note: please don’t use eval()! Executing arbitrary code contained in a string possibly constructed from user input is far too dangerous!

AggregateError

An error thrown when several errors are wrapped in a single error. This is typically raised when calling an operation such as Promise.all(), which returns results from any number of promises.

InternalError

A non-standard (Firefox only) error thrown when an error occurs internally in the JavaScript engine. It’s typically the result of something taking too much memory, such as a large array or “too much recursion”.

Error

Finally, there is a generic Error object which is most often used when implementing our own exceptions … which we’ll cover next.

Throwing Our Own Exceptions

We can throw our own exceptions when an error occurs — or should occur. For example:

  • our function isn’t passed valid parameters
  • an Ajax request fails to return expected data
  • a DOM update fails because a node doesn’t exist

The throw statement actually accepts any value or object. For example:

throw 'A simple error string';
throw 42;
throw true;
throw { message: 'An error', name: 'MyError' };

Exceptions are thrown to every function on the call stack until they’re intercepted by an exception (catch) handler. More practically, however, we’ll want to create and throw an Error object so they act identically to standard errors thrown by JavaScript.

We can create a generic Error object by passing an optional message to the constructor:

throw new Error('An error has occurred');

We can also use Error like a function without new. It returns an Error object identical to that above:

throw Error('An error has occurred');

We can optionally pass a filename and a line number as the second and third parameters:

throw new Error('An error has occurred', 'script.js', 99);

This is rarely necessary, since they default to the file and line where we threw the Error object. (They’re also difficult to maintain as our files change!)

We can define generic Error objects, but we should use a standard Error type when possible. For example:

throw new RangeError('Decimal places must be 0 or greater');

All Error objects have the following properties, which we can examine in a catch block:

  • .name: the name of the Error type — such as Error or RangeError
  • .message: the error message

The following non-standard properties are also supported in Firefox:

  • .fileName: the file where the error occurred
  • .lineNumber: the line number where the error occurred
  • .columnNumber: the column number on the line where the error occurred
  • .stack: a stack trace listing the function calls made before the error occurred

We can change the divide() function to throw a RangeError when the number of decimal places isn’t a number, is less than zero, or is greater than eight:

// division calculation
function divide(v1, v2, dp) {

  if (isNaN(dp) || dp < 0 || dp > 8) {
    throw new RangeError('Decimal places must be between 0 and 8');
  }

  return (v1 / v2).toFixed(dp);
}

Similarly, we could throw an Error or TypeError when the dividend value isn’t a number to prevent NaN results:

  if (isNaN(v1)) {
    throw new TypeError('Dividend must be a number');
  }

We can also cater for divisors that are non-numeric or zero. JavaScript returns Infinity when dividing by zero, but that could confuse users. Rather than raising a generic Error, we could create a custom DivByZeroError error type:

// new DivByZeroError Error type
class DivByZeroError extends Error {
  constructor(message) {
    super(message);
    this.name = 'DivByZeroError';
  }
}

Then throw it in the same way:

if (isNaN(v2) || !v2) {
  throw new DivByZeroError('Divisor must be a non-zero number');
}

Now add a try...catch block to the calling showResult() function. It can receive any Error type and react accordingly — in this case, showing the error message:

// show result of division
function showResult() {

  try {
    result.value = divide(
      parseFloat(num1.value),
      parseFloat(num2.value),
      parseFloat(dp.value)
    );
    errmsg.textContent = '';
  }
  catch (e) {
    result.value = 'ERROR';
    errmsg.textContent = e.message;
    console.log( e.name );
  }

}

Try entering invalid non-numeric, zero, and negative values into this CodePen demo.

The final version of the divide() function checks all the input values and throws an appropriate Error when necessary:

// division calculation
function divide(v1, v2, dp) {

  if (isNaN(v1)) {
    throw new TypeError('Dividend must be a number');
  }

  if (isNaN(v2) || !v2) {
    throw new DivByZeroError('Divisor must be a non-zero number');
  }

  if (isNaN(dp) || dp < 0 || dp > 8) {
    throw new RangeError('Decimal places must be between 0 and 8');
  }

  return (v1 / v2).toFixed(dp);
}

It’s no longer necessary to place a try...catch block around the final return, since it should never generate an error. If one did occur, JavaScript would generate its own error and have it handled by the catch block in showResult().

Asynchronous Function Errors

We can’t catch exceptions thrown by callback-based asynchronous functions, because an error is thrown after the try...catch block completes execution. This code looks correct, but the catch block will never execute and the console displays an Uncaught Error message after one second:

function asyncError(delay = 1000) {

  setTimeout(() => {
    throw new Error('I am never caught!');
  }, delay);

}

try {
  asyncError();
}
catch(e) {
  console.error('This will never run');
}

The convention presumed in most frameworks and server runtimes such as Node.js is to return an error as the first parameter to a callback function. That won’t raise an exception, although we could manually throw an Error if necessary:

function asyncError(delay = 1000, callback) {

  setTimeout(() => {
    callback('This is an error message');
  }, delay);

}

asyncError(1000, e => {

  if (e) {
    throw new Error(`error: ${ e }`);
  }

});

Promise-based Errors

Callbacks can become unwieldy, so it’s preferable to use promises when writing asynchronous code. When an error occurs, the promise’s reject() method can return a new Error object or any other value:

function wait(delay = 1000) {

  return new Promise((resolve, reject) => {

    if (isNaN(delay) || delay < 0) {
      reject( new TypeError('Invalid delay') );
    }
    else {
      setTimeout(() => {
        resolve(`waited ${ delay } ms`);
      }, delay);
    }

  })

}

Note: functions must be either 100% synchronous or 100% asynchronous. This is why it’s necessary to check the delay value inside the returned promise. If we checked the delay value and threw an error before returning the promise, the function would become synchronous when an error occurred.

The Promise.catch() method executes when passing an invalid delay parameter and it receives to the returned Error object:

// invalid delay value passed
wait('INVALID')
  .then( res => console.log( res ))
  .catch( e => console.error( e.message ) )
  .finally( () => console.log('complete') );

Personally, I find promise chains a little difficult to read. Fortunately, we can use await to call any function which returns a promise. This must occur inside an async function, but we can capture errors using a standard try...catch block.

The following (immediately invoked) async function is functionally identical to the promise chain above:

(async () => {

  try {
    console.log( await wait('INVALID') );
  }
  catch (e) {
    console.error( e.message );
  }
  finally {
    console.log('complete');
  }

})();

Exceptional Exception Handling

Throwing Error objects and handling exceptions is easy in JavaScript:

try {
  throw new Error('I am an error!');
}
catch (e) {
  console.log(`error ${ e.message }`)
}

Building a resilient application that reacts appropriately to errors and makes life easy for users is more challenging. Always expect the unexpected.

Further information:

Original article source at: https://www.sitepoint.com/

#javascript #error #handling 

Ultimate Guide to JavaScript Error Handling
Hunter  Krajcik

Hunter Krajcik

1674840840

How to Manage Error Reporting in PHP

In this quick tip on PHP error reporting, we’ll look at how to use the tools available in PHP to handle errors in a controlled way and thereby save hours of debugging.

PHP is, by definition, an “exception-light” programming language. This means that, while it does have exceptions, it will continue to execute any script regardless of what happens unless a fatal error occurs.

For example:

<?php
  echo $sitepoint;

The code above will return the following message:

Notice: Undefined variable: sitepoint in PHP shell code on line 1

PHP will only throw a notice error, and will happily continue executing. An “exception-heavy” language like Python will throw an error and halt execution.

Because of this behavior, PHP developers must be extra careful when writing their code. Unexpected results in the execution of programs might occur, because notices won’t halt the execution but may impact the correct behavior of the program.

Before we go into how to adjust the error reporting style in PHP, let’s first understand the several levels of PHP error severity.

PHP has three main types of messages: errors, notices, and warnings. These represent the different levels of severity: E_ERROR, E_NOTICE, and E_WARNING.

Errors are fatal runtime errors and are usually caused by faults in the code. This will cause PHP to stop executing.

Notices are messages caused by code that may or may not cause problems (for example, an undefined variable). These will not cause an execution halt.

Warnings are non-fatal errors and the script execution won’t be halted.

Error Logging in PHP

By default, PHP doesn’t log any errors. For that to happen, we have to specifically tell it to start logging by turning on the display_errors variable on the PHP configuration file (the php.ini file).

In this file, we can additionally tell PHP if we also want to log notices and warnings, and where this log should be recorded.

There’s also the possibility to trigger logging from within the code. To do this, we can use the error_log() function. Since error logging isn’t the main focus of this article, more information can be found here.

Changing PHP Error Reporting

We can change the default PHP error reporting behavior by using the error_reporting() function. With this function, we can set the level of errors for the duration of the script. This is done by passing one or more of the predefined error constants to the function.

For example, if we want to see not only errors but also notices we could use this:

<?php
error_Reporting(E_ERROR | E_NOTICE);

With this declaration, the script execution will be halted not only for errors but also for notices.

Suppressing Errors

We can also tell PHP to suppress specific errors by using the error control operator (@). By putting this operator at the beginning of an expression, any error that’s a direct result of that expression is silenced:

<?php
echo @$sitepoint;

This will output the value of $sitepoint if it exists, but it’s going to return a NULL and print nothing (instead of throwing a notice) if it doesn’t.

Be very careful when using this operator, as it will completely hide the error. Not only will the error not be displayed, but it also won’t be sent to the error log.

While it may seem harmless, by using this operator you’ll be masking deeper structural issues within your code and covering up potential errant behaviors.

PHP as an Exception-heavy Language

Finally, PHP can also be used as an “exception-heavy” programming language. Normal PHP errors may be thrown as exceptions by using the ErrorException class that extends the PHP Exception class.

In the following example, a user-defined function called errorhandler() is set as error handler with the set_error_handler() function. It throws an ErrorException when a fatal error occurs because a file isn’t found with the file_get_contents() function:

<?php
function errorHandler($severity, $message, $file, $line) {
   if (!(error_reporting() & $severity)) {
      return;
   }
   throw new ErrorException("Fatal Error:No such file or directory", 0, E_ERROR);
}

set_error_handler("errorHandler");

try {
   $data=file_get_contents("sitepoint.txt");
   echo $data;
} catch (ErrorException $e) {
   echo $e->getMessage();
}

By using this method, we can handle execution errors the way we handle exceptions, wrapping them in a try…catch statement with proper instructions on how to behave in such situations.

Conclusion

Summing up, PHP may handle errors in a very loose fashion. It’s up to us developers to use the available tools to better handle them so we can make the most out of the language. By using this set of tools, we can handle errors in a controlled way, saving hours of debugging this way.

Original article source at: https://www.sitepoint.com/

#php #error 

How to Manage Error Reporting in PHP
Rupert  Beatty

Rupert Beatty

1672904728

Bugsnag: Report Errors with Bugsnag

Bugsnag 🐛

Reporting errors to Bugsnag.

📦 Installation

Integrating Bugsnag in your project

Update your Package.swift file.

.package(url: "https://github.com/nodes-vapor/bugsnag.git", from: "4.0.0")

Update configure.swift

public func configure(_ app: Application) throws {
    // Configure Bugsnag.
    app.bugsnag.configuration = .init(
        apiKey: "<YOUR BUGSNAG API KEY>",
        releaseStage: app.environment.name,
        shouldReport: app.environment.name != "local"
    )

    // Add Bugsnag middleware.
    app.middleware.use(BugsnagMiddleware())
}

Reporting

BugsnagMiddleware will automatically report errors thrown by your route handlers. You can report errors manually from Application or Request.

// Reporting from Application.
app.bugsnag.report(Abort(.internalServerError))

// Reporting from Request.
app.get("test") { req in
    req.bugsnag.report(Abort(.upgradeRequired))
    return HTTPStatus.ok
}

By conforming to the BugsnagError protocol you can have full control over how your errors are reported. It has the following properties:

NameTypeFunctionDefault
shouldReportBoolOpt out of error reporting by returning falsetrue
severitySeverityIndicate error severity (.info|.warning|.error).error
metadata[String: CustomDebugStringConvertible]Additional metadata to include in the report[:]

Users

Conforming your Authenticatable model to BugsnagUser allows you to easily pair the data to a report.

extension TestUser: BugsnagUser {
    var bugsnagID: CustomStringConvertible? { 
        self.id
    }
}

Configure all user models you would like Bugsnag to report.

// Add to configure.swift.
app.bugsnag.users.add(TestUser.self)

Bugsnag will automatically check Vapor's authentication API for the configured user types and report the user's identifier if they are logged in.

Breadcrumbs

Breadcrumbs enable you to attach custom events to your reports. Leave a breadcrumb using the convenience function on Request.

req.bugsnag.breadcrumb(
    name: "Something happened!",
    type: .manual,
    metadata: ["foo": "bar"]
)

The breadcrumb types are provided by Bugsnag:

enum BugsnagBreadcrumbType {
    case error
    case log
    case manual
    case navigation
    case process
    case request
    case state
    case user
}

Key Filters

Usually you will receive information such as headers, query params or post body fields in the reports from Bugsnag. To ensure that you do not track sensitive information, you can configure Bugsnag with a list of fields that should be filtered out:

app.bugsnag.configuration = .init(
    apiKey: "foo",
    releaseStage: "debug",
    keyFilters: ["email", "password"]
)

In this case Bugsnag Reports will hide header fields, query params or post body json fields with the keys/names email and password.

⚠️ Note: If key filters are defined and Bugsnag does not know how to parse the request body, the entire body will be hidden.

🏆 Credits

This package is developed and maintained by the Vapor team at Nodes.

Download Details:

Author: Nodes-vapor
Source Code: https://github.com/nodes-vapor/bugsnag 

#swift #vapor #error 

Bugsnag: Report Errors with Bugsnag
Desmond  Gerber

Desmond Gerber

1671301320

Build a Node.js Error-handling System

Node.js developers often find themselves working with chaotic code that’s anything but clean. This can obviously cause productivity issues and outright errors. In this article, Toptal Full-stack Developer Jay Huang will introduce you to error-handling in Node.js and demonstrate how you can build a robust error-handling system yourself.

It is not hard to see that some people are struggling to handle errors, and some are even totally missing it. Handling errors properly means not only reducing the development time by finding bugs and errors easily but also developing a robust codebase for large-scale applications.

In particular, Node.js developers sometimes find themselves working with not-so-clean code while handling various kinds of errors, incorrectly applying the same logic everywhere to deal with them. They just keep asking themselves “Is Node.js bad at handling errors?” or If not, how to handle them?” My answer to them is “No, Node.js is not bad at all. That depends on us developers.”

Here is one of my favorite solutions for that.

Types of Errors in Node.js

First of all, it is necessary to have a clear understanding of errors in Node.js. In general, Node.js errors are divided into two distinct categories: operational errors and programmer errors.

  • Operational errors represent runtime problems whose results are expected and should be dealt with in a proper way. Operational errors don’t mean the application itself has bugs, but developers need to handle them thoughtfully. Examples of operational errors include “out of memory,” “an invalid input for an API endpoint,” and so on.
  • Programmer errors represent unexpected bugs in poorly written code. They mean the code itself has some issues to solve and was coded wrong. A good example is to try to read a property of “undefined.” To fix the issue, the code has to be changed. That is a bug a developer made, not an operational error.

With that in mind, you should have no problem distinguishing between these two categories of errors: Operational errors are a natural part of an application, and programmer errors are bugs caused by developers. A logical question that follows is: “Why is it useful to divide them into two categories and deal with them?”

Without a clear understanding of errors, you might feel like restarting an application whenever an error occurs. Does it make sense to restart an application due to “File Not Found” errors when thousands of users are enjoying the application? Absolutely not.

But what about programmer errors? Does it make sense to keep an application running when an unknown bug appears that could result in an unexpected snowball effect in the application? Again, definitely not!

It’s Time to Handle Errors Properly

Assuming you have some experience with async JavaScript and Node.js, you might have experienced drawbacks when using callbacks for dealing with errors. They force you to check errors all the way down to nested ones, causing notorious “callback hell” issues that make it hard to follow the code flow.

Using promises or async/await is a good replacement for callbacks. The typical code flow of async/await looks like the following:

const doAsyncJobs = async () => {
 try {
   const result1 = await job1();
   const result2 = await job2(result1);
   const result3 = await job3(result2);
   return await job4(result3);
 } catch (error) {
   console.error(error);
 } finally {
   await anywayDoThisJob();
 }
}

Using Node.js built-in Error object is a good practice because it includes intuitive and clear information about errors like StackTrace, which most developers depend on to keep track of the root of an error. And additional meaningful properties like HTTP status code and a description by extending the Error class will make it more informative.

class BaseError extends Error {
 public readonly name: string;
 public readonly httpCode: HttpStatusCode;
 public readonly isOperational: boolean;
 
 constructor(name: string, httpCode: HttpStatusCode, description: string, isOperational: boolean) {
   super(description);
   Object.setPrototypeOf(this, new.target.prototype);
 
   this.name = name;
   this.httpCode = httpCode;
   this.isOperational = isOperational;
 
   Error.captureStackTrace(this);
 }
}

//free to extend the BaseError
class APIError extends BaseError {
 constructor(name, httpCode = HttpStatusCode.INTERNAL_SERVER, isOperational = true, description = 'internal server error') {
   super(name, httpCode, isOperational, description);
 }
}

I only implemented some HTTP status codes for the sake of simplicity, but you are free to add more later.

export enum HttpStatusCode {
 OK = 200,
 BAD_REQUEST = 400,
 NOT_FOUND = 404,
 INTERNAL_SERVER = 500,
}

There is no need to extend BaseError or APIError, but it is okay to extend it for common errors according to your needs and personal preferences.

class HTTP400Error extends BaseError {
 constructor(description = 'bad request') {
   super('NOT FOUND', HttpStatusCode.BAD_REQUEST, true, description);
 }
}

So how do you use it? Just throw this in:

...
const user = await User.getUserById(1);
if (user === null)
 throw new APIError(
   'NOT FOUND',
   HttpStatusCode.NOT_FOUND,
   true,
   'detailed explanation'
 );

Centralized Node.js Error-handling

Now, we are ready to build the main component of our Node.js error-handling system: the centralized error-handling component.

It is usually a good idea to build a centralized error-handling component in order to avoid possible code duplications when handling errors. The error-handling component is in charge of making the caught errors understandable by, for example, sending notifications to system admins (if necessary), transferring events to a monitoring service like Sentry.io, and logging them.

Here is a basic workflow for dealing with errors:

 

Error handling in Node.js: basic workflow

 

In some parts of the code, errors are caught to transfer to an error-handling middleware.

...
try {
 userService.addNewUser(req.body).then((newUser: User) => {
   res.status(200).json(newUser);
 }).catch((error: Error) => {
   next(error)
 });
} catch (error) {
 next(error);
}
...

The error-handling middleware is a good place to distinguish between error types and send them to the centralized error-handling component. Knowing the basics about handling errors in Express.js middleware would certainly help.

app.use(async (err: Error, req: Request, res: Response, next: NextFunction) => {
 if (!errorHandler.isTrustedError(err)) {
   next(err);
 }
 await errorHandler.handleError(err);
});

By now, one can imagine what the centralized component should look like because we have already used some of its functions. Bear in mind that it is totally up to you how to implement it, but it might look like the following:

class ErrorHandler {
 public async handleError(err: Error): Promise<void> {
   await logger.error(
     'Error message from the centralized error-handling component',
     err,
   );
   await sendMailToAdminIfCritical();
   await sendEventsToSentry();
 }
 
 public isTrustedError(error: Error) {
   if (error instanceof BaseError) {
     return error.isOperational;
   }
   return false;
 }
}
export const errorHandler = new ErrorHandler();

Sometimes, the output of the default “console.log” makes it difficult to keep track of errors. Rather, it could be much better to print errors in a formatted way so that developers can quickly understand the issues and make sure they are fixed.

Overall, this will save developers time making it easy to keep track of errors and handle them by increasing their visibility. It is a good decision to employ a customizable logger like winston or morgan.

Here is a customized winston logger:

const customLevels = {
 levels: {
   trace: 5,
   debug: 4,
   info: 3,
   warn: 2,
   error: 1,
   fatal: 0,
 },
 colors: {
   trace: 'white',
   debug: 'green',
   info: 'green',
   warn: 'yellow',
   error: 'red',
   fatal: 'red',
 },
};
 
const formatter = winston.format.combine(
 winston.format.colorize(),
 winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
 winston.format.splat(),
 winston.format.printf((info) => {
   const { timestamp, level, message, ...meta } = info;
 
   return `${timestamp} [${level}]: ${message} ${
     Object.keys(meta).length ? JSON.stringify(meta, null, 2) : ''
   }`;
 }),
);
 
class Logger {
 private logger: winston.Logger;
 
 constructor() {
   const prodTransport = new winston.transports.File({
     filename: 'logs/error.log',
     level: 'error',
   });
   const transport = new winston.transports.Console({
     format: formatter,
   });
   this.logger = winston.createLogger({
     level: isDevEnvironment() ? 'trace' : 'error',
     levels: customLevels.levels,
     transports: [isDevEnvironment() ? transport : prodTransport],
   });
   winston.addColors(customLevels.colors);
 }
 
 trace(msg: any, meta?: any) {
   this.logger.log('trace', msg, meta);
 }
 
 debug(msg: any, meta?: any) {
   this.logger.debug(msg, meta);
 }
 
 info(msg: any, meta?: any) {
   this.logger.info(msg, meta);
 }
 
 warn(msg: any, meta?: any) {
   this.logger.warn(msg, meta);
 }
 
 error(msg: any, meta?: any) {
   this.logger.error(msg, meta);
 }
 
 fatal(msg: any, meta?: any) {
   this.logger.log('fatal', msg, meta);
 }
}
 
export const logger = new Logger();

What it basically provides is logging at multiple different levels in a formatted way, with clear colors, and logging into different output media according to the runtime environment. The good thing with this is you can watch and query logs by using winston’s built-in APIs. Furthermore, you can use a log analysis tool to analyze the formatted log files to get more useful information about the application. It’s awesome, isn’t it?

Up to this point, we mostly discussed dealing with operational errors. How about programmer errors? The best way to deal with these errors is to crash immediately and restart gracefully with an automatic restarter like PM2—the reason being that programmer errors are unexpected, as they are actual bugs that might cause the application to end up in a wrong state and behave in an unexpected way.

process.on('uncaughtException', (error: Error) => {
 errorHandler.handleError(error);
 if (!errorHandler.isTrustedError(error)) {
   process.exit(1);
 }
});

Last but not least, I am going to mention dealing with unhandled promise rejections and exceptions.

You might find yourself spending a lot of time dealing with promises when working on Node.js/Express applications. It is not hard to see warning messages about unhandled promise rejections when you forget to handle rejections.

The warning messages don’t do much except logging, but it is a good practice to use a decent fallback and subscribe to process.on(‘unhandledRejection’, callback).

The typical error-handling flow might look like the following:

// somewhere in the code
...
User.getUserById(1).then((firstUser) => {
  if (firstUser.isSleeping === false) throw new Error('He is not sleeping!');
});
...
 
// get the unhandled rejection and throw it to another fallback handler we already have.
process.on('unhandledRejection', (reason: Error, promise: Promise<any>) => {
 throw reason;
});
 
process.on('uncaughtException', (error: Error) => {
 errorHandler.handleError(error);
 if (!errorHandler.isTrustedError(error)) {
   process.exit(1);
 }
});

Wrapping Up

When all is said and done, you should realize that error-handling is not an optional extra but rather an essential part of an application, both in the development stage and in production.

The strategy of handling errors in a single component in Node.js will ensure developers save valuable time and write clean and maintainable code by avoiding code duplication and missing error context.

I hope you enjoyed reading this article and found the discussed error-handling workflow and implementation helpful for building a robust codebase in Node.js.

Original article source at: https://www.toptal.com/

#node #system #error 

Build a Node.js Error-handling System

How to Use Express.js Routes for Promise-based Error Handling

Maintainable Express.js code after scaling means making common code more feature-rich while reducing boilerplate. Find out how to enable promise-based route code and centralize both error handling and normal-results handling in Express.js apps.

The Express.js tagline rings true: It’s a “fast, unopinionated, minimalist web framework for Node.js.” It’s so unopinionated that, despite current JavaScript best practices prescribing the use of promises, Express.js doesn’t support promise-based route handlers by default.

With many Express.js tutorials leaving out that detail, developers often get in the habit of copying and pasting result-sending and error-handling code for each route, creating technical debt as they go. We can avoid this antipattern (and its fallout) with the technique we’ll cover today—one I’ve used successfully in apps with hundreds of routes.

Typical Architecture for Express.js Routes

Let’s start with an Express.js tutorial application with a few routes for a user model.

In real projects, we would store the related data in some database like MongoDB. But for our purposes, data storage specifics are unimportant, so we will mock them out for the sake of simplicity. What we won’t simplify is good project structure, the key to half the success of any project.

Yeoman can yield much better project skeletons in general, but for what we need, we’ll simply create a project skeleton with express-generator and remove the unnecessary parts, until we have this:

bin
  start.js
node_modules
routes
  users.js
services
  userService.js
app.js
package-lock.json
package.json

We’ve pared down the lines of the remaining files that aren’t related to our goals.

Here’s the main Express.js application file, ./app.js:

const createError  = require('http-errors');
const express = require('express');
const cookieParser = require('cookie-parser');
const usersRouter = require('./routes/users');

const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use('/users', usersRouter);
app.use(function(req, res, next) {
  next(createError(404));
});
app.use(function(err, req, res, next) {
  res.status(err.status || 500);
  res.send(err);
});

module.exports = app;

Here we create an Express.js app and add some basic middleware to support JSON use, URL encoding, and cookie parsing. We then add a usersRouter for /users. Finally, we specify what to do if no route is found, and how to handle errors, which we will change later.

The script to start the server itself is /bin/start.js:

const app = require('../app');
const http = require('http');

const port = process.env.PORT || '3000';

const server = http.createServer(app);
server.listen(port);

Our /package.json is also barebones:

{
  "name": "express-promises-example",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "start": "node ./bin/start.js"
  },
  "dependencies": {
    "cookie-parser": "~1.4.4",
    "express": "~4.16.1",
    "http-errors": "~1.6.3"
  }
}

Let’s use a typical user router implementation in /routes/users.js:

const express = require('express');
const router = express.Router();

const userService = require('../services/userService');

router.get('/', function(req, res) {
  userService.getAll()
    .then(result => res.status(200).send(result))
    .catch(err => res.status(500).send(err));
});

router.get('/:id', function(req, res) {
  userService.getById(req.params.id)
    .then(result => res.status(200).send(result))
    .catch(err => res.status(500).send(err));
});

module.exports = router;

It has two routes: / to get all users and /:id to get a single user by ID. It also uses /services/userService.js, which has promise-based methods to get this data:

const users = [
  {id: '1', fullName: 'User The First'},
  {id: '2', fullName: 'User The Second'}
];

const getAll = () => Promise.resolve(users);
const getById = (id) => Promise.resolve(users.find(u => u.id == id));

module.exports = {
  getById,
  getAll
};

Here we’ve avoided using an actual DB connector or ORM (e.g., Mongoose or Sequelize), simply mimicking data fetching with Promise.resolve(...).

Express.js Routing Problems

Looking at our route handlers, we see that each service call uses duplicate .then(...) and .catch(...) callbacks to send data or errors back to the client.

At first glance, this may not seem serious. Let’s add some basic real-world requirements: We’ll need to display only certain errors and omit generic 500-level errors; also, whether we apply this logic or not must be based on the environment. With that, what will it look like when our example project grows from its two routes into a real project with 200 routes?

Approach 1: Utility Functions

Maybe we would create separate utility functions to handle resolve and reject, and apply them everywhere in our Express.js routes:

// some response handlers in /utils 
const handleResponse = (res, data) => res.status(200).send(data);
const handleError = (res, err) => res.status(500).send(err);


// routes/users.js
router.get('/', function(req, res) {
  userService.getAll()
    .then(data => handleResponse(res, data))
    .catch(err => handleError(res, err));
});

router.get('/:id', function(req, res) {
  userService.getById(req.params.id)
    .then(data => handleResponse(res, data))
    .catch(err => handleError(res, err));
});

Looks better: We’re not repeating our implementation of sending data and errors. But we’ll still need to import these handlers in every route and add them to each promise passed to then() and catch().

Approach 2: Middleware

Another solution could be to use Express.js best practices around promises: Move error-sending logic into Express.js error middleware (added in app.js) and pass async errors to it using the next callback. Our basic error middleware setup would use a simple anonymous function:

app.use(function(err, req, res, next) {
  res.status(err.status || 500);
  res.send(err);
});

Express.js understands that this is for errors because the function signature has four input arguments. (It leverages the fact that every function object has a .length property describing how many parameters the function expects.)

Passing errors via next would look like this:

// some response handlers in /utils 
const handleResponse = (res, data) => res.status(200).send(data);

// routes/users.js
router.get('/', function(req, res, next) {
  userService.getAll()
    .then(data => handleResponse(res, data))
    .catch(next);
});

router.get('/:id', function(req, res, next) {
  userService.getById(req.params.id)
    .then(data => handleResponse(res, data))
    .catch(next);
});

Even using the official best practice guide, we still need our JS promises in every route handler to resolve using a handleResponse() function and reject by passing along the next function.

Let’s try to simplify that with a better approach.

Approach 3: Promise-based Middleware

One of the greatest features of JavaScript is its dynamic nature. We can add any field to any object at runtime. We’ll use that to extend Express.js result objects; Express.js middleware functions are a convenient place to do so.

Our promiseMiddleware() Function

Let’s create our promise middleware, which will give us the flexibility to structure our Express.js routes more elegantly. We’ll need a new file, /middleware/promise.js:

const handleResponse = (res, data) => res.status(200).send(data);
const handleError = (res, err = {}) => res.status(err.status || 500).send({error: err.message});


module.exports = function promiseMiddleware() {
  return (req,res,next) => {
    res.promise = (p) => {
      let promiseToResolve;
      if (p.then && p.catch) {
        promiseToResolve = p;
      } else if (typeof p === 'function') {
        promiseToResolve = Promise.resolve().then(() => p());
      } else {
        promiseToResolve = Promise.resolve(p);
      }

      return promiseToResolve
        .then((data) => handleResponse(res, data))
        .catch((e) => handleError(res, e));  
    };

    return next();
  };
}

In app.js, let’s apply our middleware to the overall Express.js app object and update the default error behavior:

const promiseMiddleware = require('./middlewares/promise');
//...
app.use(promiseMiddleware());
//...
app.use(function(req, res, next) {
  res.promise(Promise.reject(createError(404)));
});
app.use(function(err, req, res, next) {
  res.promise(Promise.reject(err));
});

Note that we do not omit our error middleware. It’s still an important error handler for all synchronous errors that may exist in our code. But instead of repeating error-sending logic, the error middleware now passes any synchronous errors to the same central handleError() function via a Promise.reject() call sent to res.promise().

This helps us handle synchronous errors like this one:

router.get('/someRoute', function(req, res){
  throw new Error('This is synchronous error!');
});

Finally, let’s use our new res.promise() in /routes/users.js:

const express = require('express');
const router = express.Router();

const userService = require('../services/userService');

router.get('/', function(req, res) {
  res.promise(userService.getAll());
});

router.get('/:id', function(req, res) {
  res.promise(() => userService.getById(req.params.id));
});

module.exports = router;

Note the different uses of .promise(): We can pass it a function or a promise. Passing functions can help you with methods that don’t have promises; .promise() sees that it’s a function and wraps it in a promise.

Where is it better to actually send errors to the client? It’s a good code-organization question. We could do that in our error middleware (because it’s supposed to work with errors) or in our promise middleware (because it already has interactions with our response object). I decided to keep all response operations in one place in our promise middleware, but it’s up to each developer to organize their own code.

Technically, res.promise() Is Optional

We’ve added res.promise(), but we’re not locked into using it: We’re free to operate with the response object directly when we need to. Let’s look at two cases where this would be useful: redirecting and stream piping.

Special Case 1: Redirecting

Suppose we want to redirect users to another URL. Let’s add a function getUserProfilePicUrl() in userService.js:

const getUserProfilePicUrl = (id) => Promise.resolve(`/img/${id}`);

And now let’s use it in our users router in async/await style with direct response manipulation:

router.get('/:id/profilePic', async function (req, res) {
  try {
    const url = await userService.getUserProfilePicUrl(req.params.id);
    res.redirect(url);
  } catch (e) {
    res.promise(Promise.reject(e));
  }
});

Note how we use async/await, perform the redirection, and (most importantly) still have one central place to pass any error because we used res.promise() for error handling.

Special Case 2: Stream Piping

Like our profile picture route, piping a stream is another situation where we need to manipulate the response object directly.

To handle requests to the URL we’re now redirecting to, let’s add a route that returns some generic picture.

First we should add profilePic.jpg in a new /assets/img subfolder. (In a real project we would use cloud storage like AWS S3, but the piping mechanism would be the same.)

Let’s pipe this image in response to /img/profilePic/:id requests. We need to create a new router for that in /routes/img.js:

const express = require('express');
const router = express.Router();

const fs = require('fs');
const path = require('path');

router.get('/:id', function(req, res) {
  /* Note that we create a path to the file based on the current working
   * directory, not the router file location.
   */

  const fileStream = fs.createReadStream(
    path.join(process.cwd(), './assets/img/profilePic.png')
  );
  fileStream.pipe(res);
});

module.exports = router;

Then we add our new /img router in app.js:

app.use('/users', require('./routes/users'));
app.use('/img', require('./routes/img'));

One difference likely stands out compared to the redirect case: We haven’t used res.promise() in the /img router! This is because the behavior of an already-piped response object being passed an error will be different than if the error occurs in the middle of the stream.

Express.js developers need to pay attention when working with streams in Express.js applications, handling errors differently depending on when they occur. We need to handle errors before piping (res.promise() can help us there) as well as midstream (based on the .on('error') handler), but further details are beyond the scope of this article.

Enhancing res.promise()

As with calling res.promise(), we’re not locked into implementing it the way we have either. promiseMiddleware.js can be augmented to accept some options in res.promise() to allow callers to specify response status codes, content type, or anything else a project might require. It’s up to developers to shape their tools and organize their code so that it best suits their needs.

Express.js Error Handling Meets Modern Promise-based Coding

The approach presented here allows for more elegant route handlers than we started with and a single point of processing results and errors—even those fired outside of res.promise(...)—thanks to error handling in app.js. Still, we are not forced to use it and can process edge cases as we want.

The full code from these examples is available on GitHub. From there, developers can add custom logic as needed to the handleResponse() function, such as changing the response status to 204 instead of 200 if no data is available.

However, the added control over errors is much more useful. This approach helped me concisely implement these features in production:

  • Format all errors consistently as {error: {message}}
  • Send a generic message if no status is provided or pass along a given message otherwise
  • If the environment is dev (or test, etc.), populate the error.stack field
  • Handle database index errors (i.e., some entity with a unique-indexed field already exists) and gracefully respond with meaningful user errors

This Express.js route logic was all in one place, without touching any service—a decoupling that left the code much easier to maintain and extend. This is how simple—but elegant—solutions can drastically improve project structure.

Original article source at: https://www.toptal.com/

#express #error #handling 

How to Use Express.js Routes for Promise-based Error Handling
Sheldon  Grant

Sheldon Grant

1669907907

Write Error Handling in Micronaut

I’m going to walk you through the process of writing error handling in Micronaut which is a very simple, but powerful way, to manage errors.

Why is Error Handling Important

Error handling is important because it allows you to gracefully handle unexpected errors in your code. By providing custom error handling, you can provide a better user experience by providing more informative error messages and by directing the user to the appropriate resources for help. Additionally, proper error handling can help prevent your code from crashing or behaving unexpectedly.

What is an Exception

When we talk about Exception Handling, there are two primary types of errors that we need to consider: checked and unchecked. Checked exceptions are those that the compiler forces you to deal with, whereas unchecked exceptions are not. In order to write error handling in Micronaut, you will need to use try/catch blocks for both types of errors.

Checked exceptions occur at compile time, such as when you try to reference a non-existent file. To handle these, you must wrap your code in a try block and catch the specific exception type that could be thrown. For example:

try { 

 // Code which may throw a checked exception 

} catch (IOException e) { 

     // Handle the exception here 
}

Unchecked exceptions are those which occur at runtime, such as when you try to divide by zero. These do not need to be caught by a try/catch block but can be if you want to handle them specifically. However, it is generally good practice to let these propagate up the call stack so that they can be dealt with at a higher level. For example:

// Code which may throw an unchecked exception 

int result = 10 / 0;  // Throws an ArithmeticException

How to Handle Exceptions in Micronaut

When you are writing code in Micronaut, it is important to be aware of how to handle exceptions. This is especially true when you are working with data sources, such as databases or web services.

There are two main ways to handle exceptions in Micronaut: try/catch blocks and error-handling interceptors.

Try/catch blocks are the most common way to handle exceptions in Java code. You can use them to wrap code that might throw an exception and handle the exception if it does occur. For example:

try {

  // Code that might throw an exception

} catch (Exception e) {

  // Handle the exception

}

Error handling interceptors are a special type of interceptor that are invoked when an exception is thrown. They can be used to do things like log the exception or send an email notification about the error. To use an error handling interceptor, you need to add it to your Micronaut configuration file:

micronaut:

  interceptors:

    - class: com.example.myapp.interceptors.MyErrorHandlingInterceptor

The Error class

The Error class is the base class for all errors in Micronaut. It provides the following methods:

  • getMessage(): Returns the error message.
  • getCause(): Returns the cause of the error, if any.
  • toString(): Returns a string representation of the error.
  • printStackTrace(): Prints a stack trace of the error to standard error.

The Exception class

The Exception class is the base class for all exceptions in Micronaut. It provides common functionality for all exceptions, such as storing a stack trace.

Conclusion

In conclusion, error handling in Micronaut is a crucial aspect of developing applications with this framework. By understanding how to properly handle errors, you can ensure that your application will be able to gracefully recover from any unexpected situations. With the tips and techniques in this article, you should now be well-equipped to tackle error handling in your own Micronaut applications.

HAPPY LEARNING!

Original article source at: https://blog.knoldus.com/

#micronaut #error 

Write Error Handling in Micronaut

How to Avoid an Error Caused By Calling A Non-existent Function

How to check if a function exists in JavaScript

An error caused by calling a non-existent function will cause JavaScript to throw an undefined error and stop running your code. To prevent the error, you can first check if a function exists in your current JavaScript environment by using a combination of an if statement and the typeof operator on the function you want to call.

Only when the typeof returns "function" will you call that function to execute it. Let’s look at the following example:

function printMessage(){
  console.log("Hello World!");
}

if(typeof printMessage === "function"){
  printMessage();
}

When the type of printMessage is anything other than "function", you don’t call the function.

Handling non-existent function with try..catch block

Alternatively, you can also use a try..catch block to handle the error when a non-existent function is called:

try {
  printMessage();
} catch (err) {
  console.log(err); // Error: "printMessage is not defined"
}

// code below won't be executed without try..catch block

console.log("abc...");
console.log("...The script execution continues...");
console.log("...even when there's an error");

Without the try..catch block, the console logs above won’t be executed by JavaScript. You can use the techniques above to check if a JavaScript function exists before calling it.

Original article source at: https://sebhastian.com/

#error #javascript 

How to Avoid an Error Caused By Calling A Non-existent Function
Rupert  Beatty

Rupert Beatty

1669699742

How to Fix The Encryption Unsuccessful Error on Your Android Phone

Android: Solve encryption unsuccessful error

When booting your Android phone back, you may see a message that says Encryption unsuccessful on the screen.

Android Encryption unsuccessful

Android Encryption unsuccessful

The full message is as follows:

Encryption was interrupted and can’t be completed. As a result, the data on your phone is no longer accessible.

To resume using your phone, you must perform a factory reset. When you set up your phone after the reset, you’ll have an opportunity to restore any data that was backed up to your Google Account.

Encryption is the process of converting information or data into code. It’s used to conceal your personal information and prevent unauthorized access.

When you boot your phone for the first time, Android will ask you to insert the password or PIN to unlock the screen.

Inserting the password or PIN is the trigger that decrypts your data into a readable format by Android.

This error happens when your Android phone is unable to encrypt the data. Instead of accessing the data as it is, Android will respond with the error above.

The cause for the error is hard to pinpoint. It can be caused by your phone’s hardware malfunctioning.

Whatever the cause, you need to remove all data from the phone’s memory to resolve the issue.

To fix the error, you need to tap the Reset Phone button at the bottom of the screen:

Android Encryption unsuccessful fix

Android Encryption unsuccessful fix

Your Android phone will begin the process of resetting your phone to its factory setting. This may take several minutes to complete.

Once done, your Android phone will reboot. You need to set up the phone as if you’re using a brand new phone.

If you still see the error message after rebooting, try to wipe the data yourself from the Android recovery mode.

To enter the recovery mode, you need to perform the following steps:

  • Turn off your phone
  • Press the power button and volume up button until you boot into Android’s recovery mode
  • Select the Wipe data/factory reset option
  • Select reboot system now option

Here’s an example of performing a factory reset on a Samsung Galaxy phone:

Even if you have a different phone model, the way to enter the recovery mode should be the same.

When you can’t enter the recovery mode, try typing [phone model] recovery mode into the YouTube search bar to see the one for your model.

Once you wipe data and reboot the phone, you should be able to set up the phone.

If you still see the error message after resetting, then it’s possible that your phone’s internal memory storage (EMMC) is not working.

You need to get the phone to the manufacturer’s customer service and ask if they can help you fix the phone.

I hope this tutorial has been helpful for you. 🙏

Original article source at: https://sebhastian.com/

#android #error 

How to Fix The Encryption Unsuccessful Error on Your Android Phone
Gordon  Murray

Gordon Murray

1669609157

How to Fix Package Android.support.annotation Does Not Exist Error

How to resolve the error package android.support.annotation does not exist

When building your Android application, you might find an error saying that the package android.support.annotation does not exist.

Here’s an example of the error:

error: package android.support.annotation does not exist
error: cannot find symbol class NonNull
Error:Execution failed for task ':app:compileDebugJavaWithJavac'.

Usually, the error above happens when you migrate your Android application to use androidx libraries.

androidx is the namespace used by Android Jetpack libraries. It’s a group of Android support libraries that help you in developing an Android application.

The androidx packages fully replace the android.support packages, and new features will be added to androidx.

When you use androidx, you need to update your Android source code and replace all import statements for android.support.annotation package with androidx.annotation package.

Here’s an example of replacing the import statement that uses FloatRange annotation:

// import android.support.annotation.FloatRange;
import androidx.annotation.FloatRange;

public class Color {
    @FloatRange(from=0.0,to=1.0)
    public float makeOpaque() {
        return (float) 0.5;
    }
}

Instead of replacing the import lines one by one, you can try to use the Android Studio’s AndroidX migration feature to help you automate the process.

Before you migrate to AndroidX, please update your annotation library dependencies to version 28.0 first:

dependencies {
    implementation 'com.android.support:support-annotations:28.0.0'
}

This is required because AndroidX version 1.0.0 is equivalent to support library version 28.0.0.

If you use lesser support library versions, other errors may occur when building your application after migration.

To start the migration, add the following two lines to your gradle.properties file:

android.useAndroidX=true
android.enableJetifier=true

Next, select Refactor > Migrate to AndroidX from your Android Studio top menu.

Once you complete the review and let Android Studio do the refactor, the required androidx dependencies should be added to your build.gradle file.

You should also see the import lines being replaced with the new ones.

If you still see the build error after migrating to AndroidX, then you need to replace the import statements manually.

Right-click on your application package to open the context menu, then select the Replace in Files… menu as shown below:

Android Studio replace in files menuAndroid Studio replace in files menu

In the pop-up window, aim to replace android.support.annotation with androidx.annotation for all of your files.

The following screenshot should help:

Replacing Android annotation importsReplacing Android annotation imports

Click Replace if you want to review the refactor one by one, or click on Replace All to refactor all occurrences at once.

The issue with the annotations library should now be resolved.

Resolve annotation error in React Native applications

If you’re building an Android application using React Native, then you need to also run the jetifier package after doing all of the steps above.

Note: You need to migrate the React Native Android application using Android Studio by opening the android/ folder in Android Studio.

When you migrate your native Java code using Android Studio, the React Native modules in the node_modules folder may still contain code that uses the Android support library.

The jetifier module refactors Java code included in your React Native application to use androidx instead of android.support namespaces.

After migrating to AndroidX using Android Studio, run the following steps with NPM:

npm install --save-dev jetifier
npx jetify

Or if you use Yarn:

yarn add jetifier
yarn jetify

The import statements in your node_modules folder that uses old Android support libraries will be replaced with androidx.

Once done, you should be able to run your React Native app:

npx react-native run-android

You might also want to include the call to jetify in your postinstall script:

"scripts": {
    "postinstall": "jetify"
}

When you update your Node module dependencies with npm install or npm update, you need to run the jetify command again.

Adding jetify as the postinstall command will let Node automatically run it after installation.

Now you’ve learned how to fix the android.support.annotation package does not exist error in your Android application.

Thanks for reading! I hope this tutorial has been useful for you. 🙏

Original article source at: https://sebhastian.com/

#android #error 

How to Fix Package Android.support.annotation Does Not Exist Error
Nat  Grady

Nat Grady

1669370291

How to Fix Unexpected Token Error When Writing JavaScript Code

How to fix JavaScript unexpected token error

Sometimes you will encounter an unexpected token error in JavaScript as follows:

let val+ = "Hello";
//Error: Unexpected token '+'

In the code above, the unexpected token error happens because the plus symbol + is reserved in JavaScript for concatenation and adding two numbers together. It can’t be used for naming variables, so JavaScript throws the unexpected token error.

As you write your JavaScript application, the unexpected token error always occurs because JavaScript expected a specific syntax that’s not fulfilled by your current code. You can generally fix the error by removing or adding a specific JavaScript language symbol to your code.

In another example, the following function code lacks the closing round bracket ) after the parameter num:

function square(num {
  return num * num;
}

But when you run the code, it says Error: Unexpected token '{' because JavaScript expects the parenthesis to be closed.

function square(num) {
  return num * num;
}

When you’re using a code editor like VSCode, you may notice the syntax color difference between the correct and the wrong code as follows:

JavaScript unexpected token causes wrong syntax color in VSCode

JavaScript unexpected token causes wrong syntax color in VSCode

As you can see from the screenshot above, the correct code will color the return letter purple, but the wrong code simply doesn’t do that.

The cause for unexpected token error for your code may be different, so you need to understand basic JavaScript rules and figure out the right solution yourself.

You could have extra brackets somewhere, like in the following code:

// Unexpected token ')'
for (i = 0; i < 10; i++))
{
  console.log(i);
}

Or you may miss a semicolon symbol ; somewhere as in the code below:

// Unexpected identifier
for (i = 0 i < 10; i++)
{
  console.log(i);
}

Whatever the case is, you need to trace the error message and see which line causes you the problem, and you have to apply the right fix yourself.

Original article source at: https://sebhastian.com/

#javascript #token #error 

How to Fix Unexpected Token Error When Writing JavaScript Code
Gordon  Murray

Gordon Murray

1669343423

Resolve the error with ListView requiring android.R.id.list id attribu

Android error: Your content must have a ListView whose id attribute is 'android.R.id.list'

When you create a ListActivity class to host a ListView object, Android may complain about the lack of the id attribute for that ListView.

For example, suppose you have a MainActivity class as follows:

public class MainActivity extends ListActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

Then, you create the following activity_main.xml layout:

<ListView 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/list" >
</ListView>

When you build and run the Android application, a RuntimeException error will occur with the following message:

E/AndroidRuntime: FATAL EXCEPTION: main
# ...
Caused by: java.lang.RuntimeException: 
Your content must have a ListView whose id attribute is 'android.R.id.list'
    at #...

The exception above happens because the ListActivity class specifically requires a ListView object that has an id attribute of @android:id/list.

The value @+id/list resolves to R.id.list while @android:id/list resolves to android.R.id.list.

To resolve the error, you need to change the android:id attribute in your ListView widget as shown below:

<ListView 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@android:id/list" >
</ListView>

Rebuild your application and run it again. This time, the error should disappear.

Also, please note that the ListActivity class has been deprecated in API level 30 (Android 11)

When you need to display a UI component with a list of items, you are recommended to use either ListFragment or RecyclerView instead.

Now you’ve learned how to resolve the missing android.R.id.list id attribute in ListActivity class. Good work! 👍

Original article source at: https://sebhastian.com/

#android #error #listview 

Resolve the error with ListView requiring android.R.id.list id attribu

How to Solve PHP Fatal Error: Unsupported Operand Types

Learn how you can Solve PHP Fatal Error: Unsupported operand types.

The PHP Fatal Error: Unsupported operand types is an error message that indicates you have used operators on values that are not supported.

PHP operators like + and - can be used on int type values. When you try to combine values like array or string with an int, the error message will appear:

// 👇 unsupported operand types: string + int
print "Hello" + 29;

This fatal error commonly occurs in PHP v8, where the execution of operands is made stricter.

In PHP v7 or below, the string will be ignored and PHP will print out the int value:

// 👇 php v7 or below
print "Hello" + 29; // 29

To solve this fatal error, you need to make sure that the operands (the values on the left or right side of the operator) are supported by PHP.

Arithmetic operators like +, -, *, and / support int and float types.

You can’t add an array and an int, or a string and a float when using these operators:

<?php
$arr = [
    "name" => "Orange",
    "price" => 5,
];

// 👇 unsupported operands: array + int
$arr + 8;

Even PHP v5 will show “Unsupported operand types” when you add an array and an int as in the example above.

When you don’t know how to fix the issue, use var_dump() to see the type of the variable like this:

<?php
$arr = [
    "name" => "Orange",
    "price" => 5,
];

var_dump($arr);

The above example will output the content of the $arr variable:

array(2) {
  ["name"]=>
  string(6) "Orange"
  ["price"]=>
  int(5)
}

Knowing that it’s an array, you can choose to perform addition to the number element, which is the price element:

<?php
$arr = [
    "name" => "Orange",
    "price" => 5,
];

// 👇 add to the price element
$arr['price'] += 8;

print $arr['price']; // 13

PHP requires you to use supported operand types for the code.

When you see the message “Fatal Error: Unsupported operand types”, you need to pay attention to the variables used as operands.

They are the variables on the left or right side of the operator symbol. You can find information about them using the var_dump() function.

Once you know the operand types, adjust your code accordingly to solve this error.

And that’s how you handle PHP Fatal Error: Unsupported operand types. Nice work! 😉

Original article source at: https://sebhastian.com/

#php #error #types 

How to Solve PHP Fatal Error: Unsupported Operand Types