ES6 Promiseか、Bluebird Promiseか、Q Promiseかなど。
与えられたオブジェクトがPromiseであるかどうかを確かめるためにどうやってテストするのですか?
もしそれが.then
関数を持っていれば - それは only 標準のライブラリが使う約束です。
Promises/A +仕様には、基本的に "then
メソッドを持つオブジェクト"であるthen
ableという概念があります。 promiseはthenメソッドを使って なんでも を同化し、また同化します。あなたが言及した約束の実装はすべてこれを行います。
specification を見てください。
2.3.3.3
then
が関数の場合、これをx、最初の引数resolvePromise、および2番目の引数rejectPromiseとして呼び出します。
また、この設計決定の理論的根拠についても説明します。
この
then
ablesの扱いにより、Promise/A +準拠のthen
メソッドが公開されている限り、promise実装は相互運用できます。また、Promises/A +の実装では、妥当なthenメソッドを使って非準拠の実装を「同化」することもできます。
代わりにPromise.resolve(x)
(QのQ(x)
)を呼び出すべきではありません。 always は任意の値または外部のthen
ableを信頼できる約束に変換します。これらのチェックを自分で実行するよりも安全で簡単です。
テストスイート :Dからいつでも実行できます。
何かが不必要にコードを複雑にするかどうかをチェックするには、単にPromise.resolve
を使います。
Promise.resolve(valueOrPromiseItDoesntMatter).then(function(value) {
})
ここに私の最初の答えがあります。それはそれ以来、約束をテストする方法として 仕様で承認 になっています。
Promise.resolve(obj) == obj
これは、 アルゴリズム がPromise.resolve
がifおよびonly ifそれは仕様の定義による約束です。
ここには別の答えがありますが、これは以前はこう言っていましたが、その時点でSafariで動作しなかったときに別の答えに変更しました。それは1年前でしたが、これはSafariでも確実に機能します。
元の回答よりも多くの人がその回答の変更されたソリューションに投票したことを考えると、間違っていると感じた場合を除き、元の回答を編集していたでしょう。私はこれがより良い答えだと信じています、そしてあなたが同意することを望みます。
更新:これは最善の解決策ではなくなりました。投票してください 私の他の答え 代わりに。
obj instanceof Promise
それをするべきです。これはネイティブのes6の約束でのみ確実に動作するかもしれないことに注意してください。
シム、promiseライブラリ、またはpromiseに似たふりをしているものを使用している場合は、ここで他の回答に示すように、 "thenable"(.then
メソッドを持つもの)をテストする方が適切かもしれません。
if (typeof thing.then === 'function') {
// probably a promise
} else {
// definitely not a promise
}
指定されたオブジェクトがES6 Promiseかどうかを確認するには、次の述語を使用できます。
function isPromise(p) {
return p && Object.prototype.toString.call(p) === "[object Promise]";
}
Call
Object.prototype
からtoString
に直接アクセスすると、指定されたオブジェクトタイプの ネイティブ文字列表現 が返されます。この場合は"[object Promise]"
です。これにより、指定されたオブジェクト
toString
メソッド。instanceof
とは対照的に またはisPrototypeOf
。ただし、 タグがSymbol.toStringTag
で変更された の特定の ホストオブジェクト は、"[object Promise]"
を返すことができます。これは、プロジェクトに応じて意図した結果である場合とそうでない場合があります(たとえば、カスタムPromise実装がある場合)。
オブジェクトがnative ES6 Promiseからのものかどうかを確認するには、次を使用できます。
function isNativePromise(p) {
return p && typeof p.constructor === "function"
&& Function.prototype.toString.call(p.constructor).replace(/\(.*\)/, "()")
=== Function.prototype.toString.call(/*native object*/Function)
.replace("Function", "Promise") // replacing Identifier
.replace(/\(.*\)/, "()"); // removing possible FormalParameterList
}
仕様の this および this section に従って、関数の文字列表現は次のようになります。
"functionIdentifier(FormalParameterListopt){FunctionBody} "
上記に応じて処理されます。 FunctionBodyは、すべての主要なブラウザーで[native code]
です。
MDN:Function.prototype.toString
これは、複数の環境コンテキストでも機能します。
あなたが非同期メソッドにいるなら、あなたはこれをすることができて、どんなあいまいさも避けることができます。
async myMethod(promiseOrNot){
const theValue = await promiseOrNot()
}
関数がpromiseを返すと、解決された値を待って戻ります。関数が値を返す場合、それは解決されたものとして扱われます。
その関数が今日約束を返さないが、明日がそれを返すか非同期として宣言されているなら、あなたは将来を見越しているでしょう。
これがコード形式です https://github.com/ssnau/xkit/blob/master/util/is-promise.js
!!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function';
then
メソッドを持つオブジェクトであれば、それはPromise
として扱われるべきです。
完全な質問に対する回答ではありませんが、Node.js 10では isPromise
という新しいutil関数が追加されているかどうかを確認することに言及する価値があります。 objectがネイティブのPromiseかどうか
const utilTypes = require('util').types
const b_Promise = require('bluebird')
utilTypes.isPromise(Promise.resolve(5)) // true
utilTypes.isPromise(b_Promise.resolve(5)) // false
あなたがTypeScriptを使っているのであれば、 "type predicate"機能を使えることを付け加えたいと思います。論理検証をx is Promise<any>
を返す関数でラップするだけで、型キャストを行う必要はありません。以下の私の例では、c
はpromiseか、c.fetch()
メソッドを呼び出してpromiseに変換したい私の型の1つです。
export function toPromise(c: Container<any> | Promise<any>): Promise<any> {
if (c == null) return Promise.resolve();
return isContainer(c) ? c.fetch() : c;
}
export function isContainer(val: Container<any> | Promise<any>): val is Container<any> {
return val && (<Container<any>>val).fetch !== undefined;
}
export function isPromise(val: Container<any> | Promise<any>): val is Promise<any> {
return val && (<Promise<any>>val).then !== undefined;
}
詳細情報: https://www.typescriptlang.org/docs/handbook/advanced-types.html
これは、 graphql-js パッケージが約束を検出する方法です。
function isPromise(value) {
return Boolean(value && typeof value.then === 'function');
}
value
は関数の戻り値です。私は自分のプロジェクトでこのコードを使っていますが、今のところ問題はありません。
it('should return a promise', function() {
var result = testedFunctionThatReturnsPromise();
expect(result).toBeDefined();
// 3 slightly different ways of verifying a promise
expect(typeof result.then).toBe('function');
expect(result instanceof Promise).toBe(true);
expect(result).toBe(Promise.resolve(result));
});