1. How do you handle errors in async/await code? What are the different approaches for error handling with Futures?
Use try-catch blocks with async/await for imperative error handling that feels natural for synchronous code. Wrap await calls in try block and catch specific exception types or general exceptions in catch blocks. This is the most readable approach for error handling in async functions, allowing you to handle errors at the point where they might occur with appropriate recovery logic. For Future chains without async/await, use catchError() to handle errors in the chain, similar to catch in promises. You can also use then() with onError parameter for handling errors. Use whenComplete() or finally block for cleanup code that should run regardless of success or failure, like closing connections or hiding loading indicators. For unhandled errors in unawaited Futures, use Future.catchError() or handle errors when creating the Future. Always handle errors in Futures you create - unhandled Future errors can cause silent failures or crash your app. For multiple Futures, use Future.wait() with eagerError parameter controlling whether to wait for all Futures or return immediately on first error. Best practices include specific error handling near the source, propagating errors up if you can't handle them locally, never silently swallowing errors without logging, and using custom exception types for different error scenarios. In UI, use try-catch to set error state triggering error UI display. Understanding these error handling patterns prevents silent failures and creates robust async code.