使用默认参数添加异步事件处理程序的正确方法是什么?

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

我向标记为 Fetch async 的第一个按钮注册了一个 'click' 事件侦听器 fetchAsync。事件侦听器使用 Fetch API 执行 HTTP POST 并报告状态。这似乎工作正常。标记为 Fetch async with default parameters 的第二个按钮几乎相同,只是事件侦听器 fetchAsyncDefault 包含默认参数 urldata。这会导致获取失败并在控制台上显示错误 TypeError: Failed to fetch 和 CSP 错误 Refused to connect to 'http://localhost:3000/[object%20PointerEvent]'

我准备了一个 simple demonstration repo 代码粘贴在下面。

使用默认参数添加异步事件处理程序的正确方法是什么?

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

.addEventListener 的回调是用正在侦听的类型的事件调用的。

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

如果您通过以下方式添加侦听器

.addEventListener('click', fetchAsyncDefault);

然后点击事件将作为第一个参数传递给 fetchAsyncDefault - 这就是您的问题所在。

如果您想明确地将零参数传递给处理程序以便使用默认参数,请执行

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