Cypress commands are queued and run asynchronously, but they are NOT real Promises — you cannot use async/await or .then() with native promise semantics. You use Cypress's .then() to work with yielded values.
When you write cy.get(...).click(), nothing runs immediately; the commands are enqueued and executed in order later by Cypress's command queue. Because they are not promises, you cannot await them, and mixing async/await with cy commands leads to bugs. To act on a command's yielded subject you use .then((subject) => {...}), which runs after that command resolves. Synchronous code between commands runs BEFORE any command executes, which surprises people who put assertions on plain variables outside the chain. Understanding the command queue explains why values must be handled inside .then and why you cannot return a value from a Cypress command like a normal function.
To read a dynamic order id and reuse it: cy.get('[data-cy=order-id]').invoke('text').then((id) => { cy.request(`/api/orders/${id}`); }); — the .then gives access to the text once the command resolves.
A candidate writes: let count = 0; cy.get('.item').then(items => count = items.length); expect(count).to.equal(5); and it fails with count still 0. Explain.