Como posso saber se um objeto é um jQuery Promise / Deferred?

Eu tenho uma função que leva um único argumento. Eu preciso ser capaz de dizer se esse argumento é um jQueryPromise ouDeferred objeto. Caso contrário, o valor pode ser de qualquer tipo e ter propriedades, portanto, não é seguro apenas a presença dos métodos prometidos.

Aqui está um exemplo de como eu gostaria que minha função se comportasse:

function displayMessage(message) {
  if (message is a Promise or Deferred) {
    message.then(displayMessage);
  } else {
    alert(message);
  }
}

Observe o tratamento recursivo das promessas: se uma promessa é resolvida com outro valor de promessa, não a exibimos, esperamos que ela seja resolvida. Se retornar mais uma promessa, repita.

Isso é importante porque, se esse não fosse o caso, eu seria capaz de usarjQuery.when:

function displayMessage(message) {
  jQuery.when(message).then(function(messageString) {
    alert(messageString);
  });
}

Isso lida com valores e promessas de valores corretamente ...

displayMessage("hello");                            // alerts "hello"
displayMessage(jQuery.Deferred().resolve("hello")); // alerts "hello"

... mas uma vez que chegamos a promessas de promessas de valores, ele se decompõe:

displayMessage(jQuery.Deferred().resolve(
  jQuery.Deferred().resolve("hello")
));                                                 // alerts "[object Object]"

jQuery.when é capaz de dizer se um valor é promissor, então aparentemente é possível. Como posso verificar?

questionAnswers(2)

yourAnswerToTheQuestion