Major difference is synchronous vs asynchronous nature.
A synchronous code was blocking though running in different thread or process and return response. There was no trigger approach for doing something else.
Async programming allowed to push piece of code in an event loop. Do something else until it executes, then after completion do something with it. This is non blocking and event based approach.
What’s wrong with WSGI?
You may ask “why not just upgrade WSGI”? This has been asked many
times over the years, and the problem usually ends up being that
WSGI’s single-callable interface just isn’t suitable for more involved
Web protocols like WebSocket.
WSGI applications are a single, synchronous callable that takes a
request and returns a response; this doesn’t allow for long-lived
connections, like you get with long-poll HTTP or WebSocket
connections.
Even if we made this callable asynchronous, it still only has a single
path to provide a request, so protocols that have multiple incoming
events (like receiving WebSocket frames) can’t trigger this.
How does ASGI work?
ASGI is structured as a single, asynchronous callable. It takes scope,
which contains details about the incoming request, send, an awaitable
that lets you send events to the client, and receive, an awaitable
which lets you receive events from the client.
This not only allows multiple incoming events and outgoing events for
each application, but also allows for a background coroutine so the
application can do other things (such as listening for events on an
external trigger, like a Redis queue).