Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

What is the correct way to add an asynchronous event handler with default parameters?

I registered a ‘click’ event listener fetchAsync to the first button labelled Fetch async. The event listener performs an HTTP POST using the Fetch API and reports the status. This seems to work correctly. The second button labelled Fetch async with default parameters is almost identical except that the event listener fetchAsyncDefault contains default parameters url and data. This causes the fetch to fail with error TypeError: Failed to fetch and a CSP error Refused to connect to 'http://localhost:3000/[object%20PointerEvent]' on the console.

I have prepared a simple demonstration repo with code pasted below.

What is the correct way to add an asynchronous event handler with default parameters?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

fetchtest.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Fetch test</title>
    <script src="/javascripts/fetchtest.js" defer></script>
  </head>
  <body>
    <h1>Fetch test</h1>
    <p id="status">status</p>
    <p id="return">return</p>
    <input id="fetchAsync" type="button" value="Fetch async" />
    <input id="fetchAsyncDefault" type="button" value="Fetch async with default parameters" />
  </body>
</html>

javascripts/fetchtest.js

const fetchAsync = async () => {
  const url = 'https://httpbin.org/post';
  const data = { node1: 'val1', node2: 'val2' };
  try {
    const response = await fetch(url, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(data),
    });
    const ret = await response.json();
    document.getElementById('status').innerHTML = 'success';
    document.getElementById('return').innerHTML = ret.data;
  } catch (error) {
    document.getElementById('status').innerHTML = 'failed';
    document.getElementById('return').innerHTML = error;
  }
};

const fetchAsyncDefault = async (
  url = 'https://httpbin.org/post',
  data = { node1: 'val1', node2: 'val2' },
) => {
  try {
    const response = await fetch(url, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(data),
    });
    const ret = await response.json();
    document.getElementById('status').innerHTML = 'success';
    document.getElementById('return').innerHTML = ret.data;
  } catch (error) {
    document.getElementById('status').innerHTML = 'failed';
    document.getElementById('return').innerHTML = error;
  }
};

document.getElementById('fetchAsync').addEventListener('click', fetchAsync);
document.getElementById('fetchAsyncDefault').addEventListener('click', fetchAsyncDefault);

>Solution :

The callback to .addEventListener is called with an event of the type that is being listened for.

const fn = (arg) => {
  console.log(arg instanceof Event);
};
window.addEventListener('click', fn);

If you add a listener by doing

.addEventListener('click', fetchAsyncDefault);

then a click event will be passed to fetchAsyncDefault as the first parameter – which is causing your problem here.

If you want to explicitly pass zero arguments to the handler so that the default ones get used, do

document.getElementById('fetchAsyncDefault').addEventListener('click', () => fetchAsyncDefault());
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading