Пожалуйста, не путайте объявление (создание) функции и вызов функции. В вашем коде вызывается функция foo, ей передается в качестве параметра тут же созданная анонимная функция, которая может вообще не быть вызвана или хоть как-то использована внутри foo. Поэтому, как заметили ранее
blo и
kuzemchik, результат зависит от кода функции foo и от ее синхронности.
В неупрощенном примере, по-видимому, вы используете Node.js, поэтому лучше воспользоваться полностью асинхронной моделью, нежели заменять функцию на синхронную, то есть в функцию getView принимать функцию, которая будет вызвана по завершении асинхронной операции и будет принимать результат завершения.
И еще, на мой взгляд, лучше явно отличать случаи ошибки и правильного исполнения, то есть в output при неудаче класть null или undefined, а не строку с «магическим» содержанием 'not exists'.
function getView(name, params, callback) {
//< Дополнительный параметр должен быть function callback(error, output)
var filepath = ...;
path.exists(filepath, function (exists) {
var view = ...,
error = null, //< Ошибки изначально нет.
output = null; //< Результата изначально нет.
if (exists) {
output = ...; //< Записываем результат выполнения. Ошибки нет.
}
else {
error = new Error('View '+ name + ' file ' + filepath + ' not found'); //< Результата нет, но есть ошибка.
console.log(error); //< Её и логируем.
}
callback(error, output); //< Вызываем обработчик завершения, в который передаем ошибку (даже если ее нет, всегда первым параметром - так принято в Node.js) и следом результат.
});
//< Ничего не возвращаем. Результат попадет в callback, когда он станет доступным.
}