Ответ
До появления Promise в JavaScript для асинхронного кода использовались колбэки (callback functions), что приводило к "аду колбэков" (callback hell) — вложенным и сложно читаемым структурам.
Пример с колбэками:
fs.readFile('file1.txt', 'utf8', (err, data1) => {
if (err) throw err;
fs.readFile('file2.txt', 'utf8', (err, data2) => {
if (err) throw err;
console.log(data1 + data2);
});
});
Также существовали библиотеки (например, async.js), которые упрощали работу с асинхронностью, но не решали проблему полностью. Позже появились Deferred (jQuery) и генераторы, но они были нестандартными или сложными. Promise (ES6) решили эти проблемы, предоставив цепочки .then() и .catch().