Способ найти, вернет ли функция обещание

Ниже у меня есть функция, которая возвращает обещание, которое разрешает true. Есть ли способ узнать, возвратит ли функция обещание?

var myPromiseFunction = function(){
  return Promise.resolve(true)
}

myPromiseFunction().then(function(value){
  console.log(value) // => true
})

function mySyncFunction(){
  return "hello"
}

willReturnPromise(myPromiseFunction) // => true
willReturnPromise(mySyncFunction) // => false

Ответ 1

Есть ли способ узнать, вернет ли функция обещание?

Нет (не вызывает его вообще). Ваш лучший регресс здесь заключается в том, чтобы полагаться на согласованность в именовании и соглашениях API.

Просто для быстрого "доказательства" неспособности проверить тип возвращаемого значения, рассмотрите следующую функцию:

function maybeAPromise() {
    if (Math.random() < .5) {
        return Promise.resolve('foo');
    } else {
        return 'bar';
    }
}

Хотя я лично считаю, что преимущества производительности динамических языков, таких как JavaScript, стоят их компромиссов, нет никаких сомнений в том, что отсутствие безопасности типа компиляции является одним из компромиссов в категории "отрицательных".

При этом Promise.resolve() удобно, если вы просто хотите заставить результат быть Promise. Например,

Promise.resolve(maybeAPromise()).then(...);

Ответ 2

Нет хорошего способа сделать это, но вы можете вызвать методы и проверить их возвращаемые значения.

function willReturnPromise(fn) {
    const result = fn();
    return result && typeof result.then === 'function';
}

Спецификация A + Promise не требует promises иметь что-либо, кроме функции с именем then, поэтому это лучшее, что вы можете сделать, если хотите, чтобы функция работала со всеми реализациями Promise.

Вызов функции и отбрасывание результата просто для определения этого не является хорошей идеей.

Ответ 3

Проверьте возвращаемое значение после его вызова. В конце концов, это JavaScript, а не какой-то статически типизированный язык. У вас есть все те же опции:

function foo(func) {
  var result = func();
  if (result instanceof Promise) {
    result.then(bar).catch(failure);
  } else {
    bar(result);
  }
}

foo(myPromiseFunction);
foo(mySyncFunction);

Но я рекомендую против таких оптимизаций, так как это увеличивает сложность. Лучше позволить Promise.resolve() сделать свое дело и свернуть ваш синхронный поток кода в ваш асинхронный. .then делает это автоматически для вас на все, что вы возвращаете, поэтому я считаю этот подход вполне читаемым.