Промисы это один из способов упорядочить Ваш асинхронный код, вполне допустимо будет сказать: "Промисы это инструмент позволяющий писать асинхронный код в синхронном стиле".
Еще до промисов в библиотеке JQuery использовался Deferred обьект, эта почти идентичная реализация стандартного обьекта Promise в современном JS.
Одна из причин появления промисов это снижение callback hell, когда из за обилия асинхронных операций, появлялось множество коллбеков, в которых происходили новые асинхронные операции, код постепенно смещался вправо, его читаемость снижалась, а поддерживать и вносить изменения в такой код становилось сложнее. В общем промисы решают задачу снижения количества коллбеков. Помогают упорядочить асинхронные операции, однако это не мешает Вам использовать промисы и с синхронными задачами.
Одна из самых частых задач с промисами в клиентском JS это отправка http запросов.
fetch('/getUser')
.then(response => response.json())
.then(console.log);
Это простейший пример, вызов функции fetch возвращает промис, результат разрешения которого можно обработать в цепочке вызовов then
Примеры могут быть сложнее, где использование промиса дает больше преимуществ, например когда необходимо выполнить несколько запросов, один за другим, или если каждый следующий запрос использует данные из прошлого запроса.
function getPosts(id) {
return fetch(`/getPosts/${id}`)
.then(result => result.json())
}
function getComments(postId) {
return fetch(`/getComments/${postId}`)
.then(result => result.json())
}
fetch('/getUser')
.then(response => response.json())
.then(getPosts);
.then(getComments)
.then(console.log)
Отправка запросов наиболее типичная задача для клиентского кода.
В NodeJS помимо http запросов, промисы наиболее часто используются в следующих задачах.
Вот тут отличная статья по промисам, разбор частых ошибок и примеры хорошего использования https://habr.com/ru/company/mailru/blog/269465/