1) (попроще, подревнее, колбеки) голый яваскрипт, и самый нехороший способ (при большой вложенности получите колбечный ад) передавайте в функцию getData в виде параметров две функции success и error и снаружи обрабатывайте их вызовы.
var success = function(data) {...}
var error = function(errorData) {...}
getData(success, error)
2) (посложнее, посовременее, промисы) есть возможность использовать промисы? То возвращайте всегда промис из функции. А дальше обрабатывайте успех/неуспех вне функции по цепочке.
var success = function(data) {...}
var error = function(errorData) {...}
getData().then(success, error)
3) (еще посложнее, совсем модерн, потоки) есть возможность использовать библиотеку rxjs (она и в js работает). Возвращайте Observable<ваш тип> и вне функции обрабатывайте результат различными функциями rxjs (map, do, combineLatext, zip, forkJoin, catch, merge ... и много других).
var success = function(data) {...}
var error = function(errorData) {...}
getData().map(success).catch(error)
Смысл в том, что ваши функции получающие данные всегда стандартно выдают инфу с данными или ошибкой. И ничего не знают о внешнем окружении.
Так делают не то, что сеньеры, а популярные яваскрипт фреймворки