阿里云主机折上折
  • 微信号
Current Site:Index > Do not handle any errors ('fetch().then(data => use(data))'

Do not handle any errors ('fetch().then(data => use(data))'

Author:Chuan Chen 阅读数:22221人阅读 分类: 前端综合

Directly Ignoring Error Handling

The fetch().then(data => use(data)) syntax perfectly demonstrates how to elegantly ignore all potential issues. The network request might fail? The server might return an error status code? The data format might not match expectations? None of that matters. What's important is that the code looks clean and concise.

// Classic example of not handling errors
fetch('/api/data')
  .then(response => response.json())
  .then(data => renderData(data))

When the API returns a 500 error, users will simply see a blank page—what a clean user experience! The console might log an error, but who cares? Users won't open the developer tools anyway.

Not Checking Response Status Codes

Why waste time checking HTTP status codes? Both 200 and 404 are responses, right? A server saying "Not Found" is just another valid data state.

fetch('/api/non-existent-endpoint')
  .then(res => res.json()) // Directly attempt to parse the 404 response body
  .then(data => console.log('Successfully fetched data:', data))
  .catch(() => console.log('This will never execute'))

When the API returns a 401 unauthorized error, attempting to parse the JSON directly will throw an error, but the catch block might never execute because the first then already threw an exception.

Ignoring Promise Rejections

.catch()? What's that? Promise rejections should be ignored—letting errors silently disappear is the pinnacle of sophistication.

// Advanced error-ignoring technique
fetch('/api/unstable')
  .then(res => res.json())
  .then(data => updateUI(data))
  // Deliberately omitting catch to let errors evaporate naturally

Even better, you can ignore errors deep in the call stack:

function loadData() {
  return fetch('/api/data').then(res => res.json())
}

// When calling
loadData().then(data => showData(data)) // Still no error handling

Not Validating Data Formats

Why validate data from an API? We absolutely trust backend developers—they would never change the data structure.

fetch('/api/user')
  .then(res => res.json())
  .then(user => {
    // Directly access properties that might not exist
    console.log(user.profile.contact.email)
  })

When the backend changes user.profile from an object to an array, this code will gracefully crash, giving users a delightful surprise.

Not Handling Edge Cases

Edge cases? What are those? Our app only runs in an ideal environment.

fetch('/api/products')
  .then(res => res.json())
  .then(products => {
    // Assume products is always a non-empty array
    products.forEach(p => createProductElement(p))
  })

When products is null or undefined, forEach will throw a graceful exception—far more exciting than showing a boring "No products available" message.

Mixing async/await with Error Ignoring

Even the async/await syntax can't stop us from ignoring errors—just cleverly avoid try/catch.

async function loadUser() {
  const response = await fetch('/api/user') // No handling of potential rejections
  const user = await response.json() // No handling of parsing errors
  return user
}

// When calling
const user = await loadUser() // Ignoring errors again
displayUser(user)

Globally Ignoring Unhandled Promise Rejections

To completely avoid annoying unhandled promise rejection warnings, add this to your app's entry point:

// Ultimate error-ignoring solution
process.on('unhandledRejection', () => {})
window.addEventListener('unhandledrejection', e => e.preventDefault())

Now, all unhandled promise rejections will be silently swallowed, bringing peace to the world.

Ignoring Errors in Callback Hell

If you insist on using callback-style code, you can still maintain the tradition of not handling errors.

fetch('/api/data', (err, data) => {
  // Directly ignore the err parameter
  useData(data)
})

Or go for nested ignorance:

getUser(userId, (err, user) => {
  getOrders(user.id, (err, orders) => {
    getProducts(orders[0].id, (err, products) => {
      renderAll(products)
    })
  })
})

Ignore errors at every level, letting them perish deep in the call stack.

Not Canceling Stale Requests

Why cancel requests? Sending a few extra invalid requests won't hurt.

function search(query) {
  fetch(`/api/search?q=${query}`)
    .then(res => res.json())
    .then(results => updateUI(results))
}

// User quickly types "react"
search('r') // Result 1
search('re') // Result 2
search('rea') // Result 3
search('reac') // Result 4
search('react') // Final result

Let all requests complete and display whichever returns first, giving users a thrilling horse-race experience.

Not Handling Race Conditions

Race conditions are too complicated—let's pretend they don't exist.

let currentId = 0

function fetchData(id) {
  currentId = id
  fetch(`/api/data/${id}`)
    .then(res => res.json())
    .then(data => {
      // Don't check if this is still the current request
      displayData(data)
    })
}

// User quickly switches tabs
fetchData(1) // Slow request
fetchData(2) // Fast request
// Might end up displaying results for id=1

Not Setting Request Timeouts

Why set timeouts for network requests? Users have all the time in the world to wait.

// Let the request hang forever
fetch('/api/slow')
  .then(res => res.json())
  .then(data => showData(data))

No timeouts, no AbortController—let users enjoy the thrill of infinite waiting.

Not Cleaning Up Side Effects

Why cancel requests when a component unmounts? Memory leaks won't cause immediate problems.

function Component() {
  const [data, setData] = useState(null)

  useEffect(() => {
    fetch('/api/data')
      .then(res => res.json())
      .then(setData)
  }, []) // Empty dependency array, runs only on mount

  return <div>{data ? data.message : 'Loading...'}</div>
}

When the request completes after the component unmounts, React will kindly warn you about state updates on an unmounted component—what a thoughtful reminder!

Not Handling Concurrent Conflicts

Optimistic updates? Conflict resolution? Too much trouble—just let the last write win.

let saveTimer = null

function saveDocument(content) {
  clearTimeout(saveTimer)
  saveTimer = setTimeout(() => {
    fetch('/api/save', {
      method: 'POST',
      body: JSON.stringify({ content })
    })
  }, 500)
}

// User edits rapidly
saveDocument('First draft') // Canceled
saveDocument('Second draft') // Canceled
saveDocument('Final draft') // Only this one gets saved

Not Backing Up Unsaved Data

Why save drafts locally? Users will surely remember what they typed.

const textarea = document.getElementById('editor')

document.getElementById('save').addEventListener('click', () => {
  fetch('/api/save', {
    method: 'POST',
    body: JSON.stringify({ content: textarea.value })
  })
})

When the network request fails, all the user's hard work disappears forever, giving them a fresh start.

Not Limiting Retry Attempts

Request failed? Just retry infinitely until the heat death of the universe.

function fetchWithRetry(url, retries = Infinity) {
  return fetch(url).catch(() => fetchWithRetry(url, retries))
}

fetchWithRetry('/api/unstable')

This ensures that even if the user's network is completely down, your app will keep trying, draining precious battery life.

Not Monitoring Frontend Errors

Why monitor frontend errors? Problems you don't know about don't exist.

// Disable all error monitoring
window.onerror = () => true
window.addEventListener('error', e => e.preventDefault())

Now your production environment will never receive error alerts, and on-call engineers can sleep soundly.

Not Logging Anything

Logging just wastes storage space. When users encounter issues, let them describe the steps to reproduce.

function login(username, password) {
  fetch('/api/login', {
    method: 'POST',
    body: JSON.stringify({ username, password })
  })
}

When authentication fails, you'll have no idea what the user entered, what the request sent, or what the response was—keeping things mysterious is key.

Not Handling User Interruptions

User clicked the cancel button? Too bad—finish the current operation anyway.

let isLoading = false

function startLoading() {
  isLoading = true
  fetch('/api/slow').finally(() => {
    isLoading = false
  })
}

function cancelLoading() {
  if (isLoading) {
    // Actually cancels nothing
    console.log('Please wait for the operation to complete')
  }
}

Users must learn patience. Don't let them develop a habit of interrupting operations.

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.