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

Time:03-20

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 PointerEvent]' 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?

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

CodePudding user response:

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());
  • Related