こんにちは、みなさん!
グローバルPromiseオブジェクトの代わりにbluebirdを使用しています。 @lheckerによって公開されたtypedefを最新バージョンに更新しようとしましたが、問題が発生しました。グローバルPromsie
は、デフォルトではオーバーロードされていません。
以前の行動をどのように達成できますか? たとえば、bluebird-global.d.tsを使用できますか?
私見では、以前のBluebirdの定義も、グローバル名前空間に大量にリークされたため、適切なソリューションではありませんでした。冗長な作業を減らすことは良い考えだと思います。
ただし、以前の定義が機能する方法は、 declare var Promise: PromiseConstructor;
を定義することですが、 PromiseConstructor
は以前の(グローバルに定義された)Bluebirdインターフェイスでした。
つまり、ローカルの*.d.ts
ファイルを作成し、このようなものを追加すると、おそらく機能する可能性がありますか?
import Bluebird = require("bluebird");
declare var Promise: Bluebird<any>;
多分うまくいくかもしれませんか?
残念だけど違う。 私はたくさんのコードを持っているので、次のように書かれています:
declare function doLoadData(): Promise<Data>
ご覧のとおり、関数はPromise<T>
を返します。これは、ブルーバードではなく、標準のPromsie
です。 var Promise: Bluebird<any>
の宣言インターフェイスではなく、標準のPromiseコンストラクターをオーバーロードします。
このため、2.0タイピングに戻しました。
@Strateああくそー私はこれについて私がどう思うか、そして私たちが何をしようとすべきかについて長いコメントを書きました。 しかし、提出するのを忘れたようで、ついに失われました...
多くの人がこの問題を抱えているようです。
問題を示すリポジトリを作成しました: https ://github.com/d-ph/typescript-bluebird-as-global-promise
git clone && npm install
&& npm run tsc
問題:
サードパーティのd.ts
ファイルはPromise
に対して入力されます。 このPromise
は、typescriptのlib.es6.d.ts
( "target": "es6"
の場合)または他のライブラリ、たとえばcore-js
(typescriptを使用してes5にコンパイルする場合に非常に人気があります)によって定義されます。 。 最新のbluebird.d.ts
は、グローバルPromise
として宣言されていませんが、bluebird.jsはそれ自体をグローバルPromise
として公開しています。
結果:
開発者は、サードパーティのコードから返されたPromiseでbluebirdの機能を使用できません(コンパイルは失敗します)。
期待される結果:
開発者は、サードパーティのコードから返されたPromiseでbluebirdの機能を使用できます(コンパイルは成功します)。
ブルーバードタイピングのメンテナーが誰なのかわかりません。 @lhecker 、あなたはgit blame
によって返される不運な人です。 上でリンクしたgithubプロジェクトがコンパイルされるような方法でbluebirdタイピングを使用する理由として好ましい理由を教えてください。
現在のウォークアラウンド:
Promise
関数の場合、次のように使用します: Promise["config"]({}); Promise.resolve("foo")["finally"](() => { console.log("lol"); })
コンパイラをサイレントにします。 つまり、配列アクセス演算子を使用します: [""]
import * as Bluebird from 'bluebird';
declare global { export interface Promise<T> extends Bluebird<T> {} }
Bluebirdの静的関数には、 Promise.config({})
Bluebird.config({})
を使用します。
欠点は、IDEがこのハッキングを正しく解釈するのに苦労していることです。
うーん...皆さんが私や他の多くの人とは違う方法でBluebirdを使用しているので、皆さんがこれに問題を抱えることは私にとってちょっと予期していませんでした。 実際、私は自分でタイピングを書くことさえしませんでした! 3.0の既存のものだけをここからコピーしただけです。なぜなら、3.0のタイピングを使用する方が、何も入力しないよりも優れているからです。
問題は、TypeScriptが向かっている現在の方向は明らかにmodules > globals
であり、これは私が本当に承認していることです。 ただし、これは、モジュールがグローバルオブジェクトを変更してはならないことも意味します。特に、 Bluebird
がすべての場合にグローバルPromise
を置き換えるわけではないことを考慮する場合はそうです。 またはそのように言うと:
コード内のどこかで文字通りPromise.noConflict()
を呼び出すと、「型安全性」はどうなりますか? tsc
ですべてが正常であると通知された場合でも、グローバルPromise
タイプが元のタイプに戻り、コードがクラッシュします。
そうそう... @ d-ph。 2番目のウォークアラウンドは、モジュールシステムの精神に基づいているため、ずっと実行することを検討する必要があります。 しかし、これはライブラリにとって理想的なソリューションにすぎないことを私は知っていますが、アプリケーションにとっては本当に迷惑になる可能性があります。 私は、アプリケーションシステムが少なくともグローバルPromise
オブジェクトを確実に置き換えることができ、2.0で利用可能だったように、そのユースケースに一致する型を使用できる必要があることに同意します。
結局、TypeScriptのイデオロギーに照らして、グローバルなPromise
型を拡張することは、非常に慎重に行う必要があり( noConflict()
の問題などを覚えておいてください)、そうであればオプトインとしてのみ行う必要があると思います。
IMOの今後の方法は、 bluebird.d.ts
ファイルにあるのと同じインターフェイス宣言を使用してグローバルPromise
オブジェクトを拡張するある種のbluebird-global.d.ts
(または同様の)ファイルを作成することです。 また、それらを使用する必要がある場合は、常に含めるのではなく、明示的にインポートする必要があります。 そうすれば、ほとんどのユースケースで、特にライブラリを作成するときに、アプリケーションでグローバルなPromise
を上書きするという追加の利点にアクセスしながら、安全で正しい入力を行うことができます。
このアイデアが良いアイデアだと思っていて、時間があれば、PRを作成できればいいと思います。 多くの人がそのような貢献に本当に満足していると確信しています。 🙂
私は現在、時間の不足と現時点でそのようなタイピングを必要としないために、それらのタイピングを書く立場にないので、このように言い換えています。 ご理解いただければ幸いです。
@lhecker私はあなたに同意できると思います。 Promiseをbluebirdのものにグローバルにオーバーライドする場合、typescriptコンパイラのみをハックし、現実の世界はハックしないためです。 たとえば、オーバーライドされPromise
を使用すると、typescriptはfetch
がbluebirdのものを返すと見なします。
import `whatwg-fetch`;
let result = fetch("anyurl"); // this is NOT bluebird promise, but typescript think that it is.
fetch
をbluebirdのPromise.resolve
にラップしないと、たとえば、$# result
の.finally
メソッドを取得できません。
import `whatwg-fetch`;
fetch("anyurl").then().finally() // goes to runtime error with overriden global promise, but should be compile error.
したがって、使用法ごとにbluebird
を明示的にインポートする方が、より良い解決策だと思います。
import Promise from "bluebird";
import `whatwg-fetch`;
Promise.resolve(fetch("anyurl")).then().catch() // no compile error, no runtime error
コードをリファクタリングします。
回答ありがとうございます、 @ lhecker 。
私はあなたが言ったことすべてに同意します。 そして、サードパーティのコードをPromise.resolve()
メソッドでラップする@Strateのソリューションが好きで、es6のpromiseをBluebirdに(またはBluebirdをBluebirdに変換します。実行時にBluebirdのpromiseをグローバルに保ちたいので、エラーを正しく処理するためにサードパーティのコードに依存する必要はありませんが、それは重要ではありません)。
これを正しく行う方法がわからなかったようです。 他の人が恩恵を受けると思うのは、この問題に対処する方法に関するドキュメントが増えることです。ブラウザプログラミングの世界から来た人は誰でも(nodejs / typescriptからではなく)次のようにヒットするからです。
npm install <absolutely everything that uses es6 promise>
npm install bluebird @types/bluebird
また、将来の参考のために、この「サードパーティのコードがes6Promiseに対して入力された場合の使用方法」セクションをどこかに文書化しておくと便利です。 つまり、
import * as Bluebird from 'bluebird';
declare global { export interface Promise<T> extends Bluebird<T> {} }
と
import * as Promise from 'bluebird';
import { Observable } from "rxjs";
let observable = Promise.resolve(new Observable<number>().toPromise());
readmeまたはbluebird.d.tsファイルの上部にあるdocブロックにあります。
どう思いますか?
Promise
のグローバルオーバーライドからブルーバードのものへの移行を完了しましたが、サードパーティライブラリがブルーバードのものとして扱われていたES6Promiseを返すという問題がいくつか見つかりました。 したがって、その移動を行うと、コードベースもクリーンアップされました。 Promise
のグローバルオーバーロードから移行することをお勧めします。 乾杯 :)
私はmodules > globals
を理解していますが、議論(および/または現実)のために、私は大規模なブラウザーSPAに取り組んでおり、PromiseポリフィルとしてBluebirdを使用するタスクを課されているとしましょう。
@ d-phのコンテンツを使用して@lheckerによって提案されたbluebird-global.d.ts
修正を試しています。
import * as Bluebird from 'bluebird';
declare global { export interface Promise<T> extends Bluebird<T> {} }
typings/modules/bluebird-global/index.d.ts
typings
を介してインストールしました:
// Generated by typings
// Source: src/bluebird-global.d.ts
declare module 'bluebird-global' {
// via https://github.com/DefinitelyTyped/DefinitelyTyped/issues/10801
import * as Bluebird from 'bluebird';
global { export interface Promise<T> extends Bluebird<T> {} }
}
しかし、私がすべてを構築しようとすると、TypeScript(v1.8.2)は次のように文句を言います。
ERROR in /path/to/typings/modules/bluebird-global/index.d.ts
(6,27): error TS2665: Module augmentation cannot introduce new names in the top level scope.
ERROR in /path/to/src/bluebird-global.d.ts
(2,35): error TS2665: Module augmentation cannot introduce new names in the top level scope.
global-modifying-module.ts
のMSの例を見てみました
https://www.typescriptlang.org/docs/handbook/declaration-files/templates/global-modifying-module-d-ts.html
そして、このエラーメッセージに関連するTSの問題
https://github.com/Microsoft/TypeScript/issues/6722
しかし、私は自分が何をすべきか途方に暮れています。 誰か助けてもらえますか?
こんにちは。
問題と解決策を示している私のリポジトリを確認していただけますか? リンク。 サードパーティからのすべての約束をbluebirdのPromiseコンストラクターにラップすることを決定するまで、私はそれに非常に満足していました。これは私が現在行っていることです。 readmeの手順を実行した後はコンパイルできませんが、コメントを解除した後は、
// declare global {
// export interface Promise<T> extends Bluebird<T> {}
// }
コンパイルしますか?
私のリポジトリはTS2(現在は安定しています)を使用しており、1.8.2を使用しているとのことです。 TSを2にアップグレードすると、何が起こるかを確認してください。
最後に、ソリューションをグローバルd.ts
ファイルに配置する際に問題が発生しました。 私はそれを私のwebpackコンパイルのすべてのエントリポイントに追加することになり、問題を解決しました(これは今では理にかなっています)。 jsの設定はわかりませんが、コンパイル中に失敗するすべてのファイル(または少なくとも1つのファイル)に修正を加えて、それが役立つかどうかを確認してください。
また、BluebirdのPromise
実装をグローバルPromise
として「登録」できるようにしたいと思います。 私はこのスレッド全体を読みましたが、一部をフォローしていません。 サードパーティのライブラリがネイティブ(Bluebird以外など)のPromise
実装を返すことを示唆する部分。 そのサードパーティのコードがある時点で、グローバルレベルでBluebirdの実装に置き換えられたPromise
コンストラクター( new Promise(...)
)を呼び出している場合、これはどのようになりますか?
<script src="//.../bluebird.min.js"></script>
<script>
var promise = fetch("some url");
promise.finally(...);
</script>
ネイティブのPromise
実装を置き換えたBluebirdを含めたので、これはうまく機能しないでしょうか?
最後に、実行時にこの完全なグローバル置換を実行している場合、コンパイル時にすべてのPromiseもBluebirdに置換されるように、これについてTypeScriptに通知できるはずです。
私は何が欠けていますか?
(使用している)distバージョンのbluebirdを使用する場合、グローバルPromiseがBluebirdになっているため、サードパーティのライブラリはBluebirdを使用します。 あなたはこの部分を正しく理解します。 人々は、Bluebirdのnode.jsの使用法について話しているので、そうではないと言います。
このスレッド全体は、tsをその仮定(グローバルなPromiseはBluebirdである)でコンパイルするためのそれほど明白ではない方法に関するものです。 あなたがそれをなんとかすることができたなら(例えばdeclare global {}
のものを介して)、あなたは終わりです。
@ d-phしかし、私の持ち帰りは、1回だけではなくすべての*.ts
ファイルでそれを行わなければならないということです-それは正しいですか? たぶん、この問題の最終的な「解決策」の要約が良いでしょう。 :)
ええ、ほら、ここには単純なjust copy&paste this line to your X file and everyone and their dog are happy now
のような解決策はありません。 または、少なくとも私はそれを認識していません。
私が最後にあなたをチェックしたとき:
import * as Bluebird from 'bluebird'; declare global { export interface Promise<T> extends Bluebird<T> {} }
行をすべてのエントリポイント* .tsファイルにコピーして貼り付けるか、または繰り返しますが、解決策1では、すべてのファイルではなく、エントリポイントファイルにのみそのコードを配置する必要があります。 少なくとも、これは私のために働いたものです(webpack + awesome-typescript-loader)。
別の解決策を見つけた場合、それは文字通り開発者が1つのファイルに1行だけを入れる必要があるので、コミュニティと共有してください; p
ありがとう@ d-ph-「すべてのエントリポイント* .tsファイル」の意味を確認できますか?
うん。 「エントリポイント」の.tsファイルは.tsファイルであり、 <script>
タグを介してHTMLにロードします。 つまり、これはコンパイルを開始するファイルです。
さっそくグーグルした後、私はこれを見つけました(わざわざ読んではいけません)。 つまり、bluebird.d.tsにglobal { export interface Promise<T> extends Bluebird<T> {} }
を手動で追加した場合、他の場所でこれについて再度言及する必要はありません。 今はテストする時間がありませんが、作成したテストgithubリポジトリでテストしましたが、動作しているようです。
つまり、bluebird.d.tsをダウンロードして、これを変更します。
// Generated by typings
// Source: bluebird.d.ts
declare module 'bluebird' {
// Type definitions for Bluebird v3.x.x
// Project: http://bluebirdjs.com
class Bluebird<R> implements Bluebird.Thenable<R>, Bluebird.Inspection<R> {
これに:
// Generated by typings
// Source: bluebird.d.ts
declare module 'bluebird' {
// Type definitions for Bluebird v3.x.x
// Project: http://bluebirdjs.com
global { export interface Promise<T> extends Bluebird<T> {} }
class Bluebird<R> implements Bluebird.Thenable<R>, Bluebird.Inspection<R> {
明らかに、これは理想的ではありません。特に、 @types/bluebird
(カスタムのハッキングされたbluebird.d.tsを使用するため、今すぐ削除する必要があります)を使用する場合は、そうです...
だから私はすでに_stubs.d.ts
ファイルを持っていて、それに以下を追加しました、そして私はずっと近くにいます。 Promise
にfinally
が存在しないという苦情はもうありませんが、何らかの理由で、 Promise
にdelay
が存在しないというエラーが発生します。 bluebird.d.ts
を編集する必要はありませんでした。 調査しますが、これは素晴らしい解決策かもしれません!
declare module "bluebird-global" {
import * as Bluebird from "bluebird";
global { export interface Promise<T> extends Bluebird<T> { } }
}
編集: delay
に関する私の問題は、静的に呼び出していたためでした(例: Promise.delay(2000)
。
上記の解決策では、関数がPromise<T>
を返すと、このエラーが発生します。
エラーTS2322:タイプ 'Bluebird
'はタイプ' Promiseに割り当てることができません '。
これは、 Promise
をBluebird
に置き換えたため、 then
などを使用するたびに、戻り値がBluebird<T>
になるためだと思います。 Promise<T>
の。
これがこのハックの私の最終バージョンです。 私はこれをするのは好きではありませんが、他のオプションよりも好きです。 基本的に、インターフェイスで使用していることを繰り返して、戻り値のタイプを$#$ Bluebird
$#$ではなくPromise
に変更する必要があります。 これは、それ以外のBluebird定義ファイルからの直接のコピーアンドペーストです。
_stubs.d.ts
declare module "bluebird-global" {
import * as Bluebird from "bluebird";
global {
export interface Promise<T> extends Bluebird<T> {
then<U1, U2>(onFulfill: (value: T) => U1 | Bluebird.Thenable<U1>, onReject: (error: any) => U2 | Bluebird.Thenable<U2>): Promise<U1 | U2>;
then<U>(onFulfill: (value: T) => U | Bluebird.Thenable<U>, onReject: (error: any) => U | Bluebird.Thenable<U>): Promise<U>;
then<U>(onFulfill: (value: T) => U | Bluebird.Thenable<U>): Promise<U>;
then(): Promise<T>;
finally<U>(handler: () => U | Bluebird.Thenable<U>): Promise<T>;
}
}
}
公式のbluebird-global
またはbluebird-override
の定義があると便利です。これは、既存の定義によく似ていますが、 Bluebird
Promise
をどこでも使用します。
解決策を見つけることができてよかったです。
完全を期すために: @ ProTipが言ったように、 bluebird-2.0.d.ts
JustWorksTMを使用します。 npm install @types/[email protected]
を使用してインストールし、tsconfig.jsonのcompilerOptions.types
に追加するだけです。
{
"compilerOptions": {
// (...)
"types": [
"bluebird"
]
},
"include": [
"src/**/*.ts"
]
}
その.d.tsと現在のBluebirdバージョン(つまり3.x)の違いは、手動でハッキングすることをお勧めします。
JustWorksTMとは、次のことを意味します。
a)es5ターゲット
b)es6ターゲット
c)core-jslibを使用したes5ターゲット
誰かがビルドセットアップ(webpack + awesome-typescript-loader)を使用しているかどうかに関係なく。 さらに、PhpStormIDEはまったく混乱していません。
私は今日この問題を見て時間を過ごし、実際にはMicrosoft / TypeScriptでこれらの2つのチケットを作成/更新しました: https ://github.com/Microsoft/TypeScript/issues/10178とhttps://github.com/Microsoft/TypeScript / issues / 12382 。 私の考えは、あなたが言ったように(そしてあなたの前にいくつか)、 bluebird-global.d.ts
ファイルが必要だということです。 コードの重複を避けるために、これでうまくいくことがわかりました。
// bluebird-global.d.ts
import * as Bluebird from "bluebird";
export as namespace Promise;
export = Bluebird;
前述の2つのチケットが解決されるか、回避策が見つかった場合。 それまでの間、ブラウザのコーディングにはbluebird-2.0.d.tsを使用することをお勧めします。
@JoshMcCullough
そのサードパーティのコードがある時点で、グローバルレベルでBliebirdの実装に置き換えられたPromiseコンストラクター(新しいPromise(...))を呼び出している場合、これはどのようになりますか?
とても簡単。 ブラウザのコンソールで試してください(Chromeを推奨):
var NativePromise = Promise;
window.Promise = function() {}; // try to overload NativePromise
NativePromise === Promise; // false. Seems it is overloaded!
// And now, let check with some native code, which return Promise, for example fetch
Object.getPrototypeOf(fetch("")) === Promise.prototype; // false, Whoops!
Object.getPrototypeOf(fetch("")) === NativePromise.prototype; // true! Double whoops!
こんにちは。 私はこれをやっていて、それはかなりスムーズです。 まず第一に、図書館プロジェクトをブルーバードに依存しないでください。 アプリケーションプロジェクトの場合、ブルーバードをインポートしますが、タイピングはインポートしません。 アプリケーションのエントリポイントで、次のようにします。
global ['Promise'] = require( 'bluebird')
これにより、アプリケーションと含まれているすべてのライブラリのグローバルPromiseオブジェクトが置き換えられます。
こんにちは、みんな、
@types/bluebird-global
が利用可能になりました。 これらのタイピングはボンネットの下で@types/bluebird@^3.0
を使用し、グローバルPromise
でbluebirdのメソッドを使用できるようにします(つまり、tsコンパイルは失敗しません)。
使い方はこちらをお読みください。
素晴らしい、ありがとう@ d-ph!
@ d-ph @types/bluebird-global
をありがとう。 グローバルPromiseの代わりにbluebirdを使用するには、プロジェクトで何らかのインポートと再割り当てを行う必要がありますか?
npm install --save-dev @types/bluebird-global
次に、タイピングに含まれている指示に従います:リンク(リンクは2017-04-02に更新されました)。 これだけでうまくいくはずです(つまり、手動でインポート/再割り当てする必要はありません)。
補足として、 package.json::devDependencies
に@types/bluebird
を記載する必要はありません。これは、自動的に暗示されるためです。
前のコメントのリンクに更新:リンク
@MichaelTontchev @ d-ph Promise.Inspection
インターフェースをbluebird-globalに追加できる可能性はありますか?
こんにちは@ksnyde。
私と話してください。 私はメンテナです。
このPromise.Inspectionを参照していることを確認してください。
そのインターフェースからのすべてのメソッドは、 bluebird-global
を介して公開されます。 つまり、以下がコンパイルされます。
let promiseInspectionTest = new Promise<void>((resolve) => {});
promiseInspectionTest.value();
したがって、これをbluebird-global
Promise.Inspection
として公開するように要求しているように思われます。
これが、代わりに以下を使用することの大きな後退であるかどうかを教えてください。
import * as Bluebird from "bluebird";
class Foo<T> implements Bluebird.Inspection<T> {
}
bluebird-global
を使用しているので、明示的なdevDependencies
なしで、そのような元のbluebird
タイプをインポートすることもできます。
lib.d.ts
からの標準のPromiseタイピングでこれらのタイピングを機能させるのは微妙な芸術であるため、その背後にある確固たる理由なしに、グローバルPromise
をこれ以上拡張したくありません。 bluebird
タイピングから直接このインターフェースにアクセスすることを強くお勧めします。ある日JavaScriptの達人がPromise.Inspection
を標準に追加し、 bluebird-global
タイピングを壊してしまう可能性があるためです。エンドユーザーに不必要な問題を引き起こします。
また、インターフェイスを追加したとしても、DTのメンテナは最近PRで忙しいので、インターフェイスがmaster
にマージされるまで不特定の時間を待つ必要があります。
乾杯。
私は確かにあなたが議論したアプローチを当分の間使用してきました、そしてそれは適切な回避策です。 あるいは、「回避策」は間違った命名法かもしれません。
私の理解/認識は、bluebird-globalの背後にある考え方は、bluebirdが提供するPromise機能のスーパーセットを公開することでした。その場合、ユーザーとしてBluebird.Inspection
がPromise.Inspection
で公開されることを期待します。 ただし、Promisesの公式APIサーフェスでBluebirdを使用することだけを目的としている場合は、この「回避策」が実際には適切な長期的なソリューションであると思います。
私は自分の解釈を好みますが、必要に応じて、ここに示すソリューションを使用しても問題ありません。
私は確かにあなたがあなたの期待でどこから来ているのかわかりますが、私がbluebird-global
を作成した主な理由は、サードパーティのコードから作成されて返されたPromiseが実際にはBluebirdのpromiseのインスタンスであることをTypeScriptに知らせるためでした。他に_迷惑ではない_代替手段はありませんでしたが、グローバルPromiseシンボル上のすべてのBluebirdのインスタンスと静的メソッドを公開することでした。 前に述べたように、それが行われる方法は、単純なclass Promise<T> extends Bluebird<T> {}
ではなく(元々はそうでしたが)、慎重にパッチが適用されたグローバルPromiseシンボルです。 そして、私が述べたように、私はむしろ、文字通りあなたの髪を頭から引き抜かせることがない、既知の代替案があるものを維持する必要を避けたいと思います。
これに「いいえ」と言ってすみません。 この特定の機能を要求する人がもっといる場合は、追加することを再検討します。 私はここで権威を持っているように聞こえたくありません-これはオープンソースプロジェクトであり、おそらく誰もがこの機能を押し込むことができます。それを維持するためのコストを上回らない。
乾杯。
理にかなっています。 あなたのアプローチの背後にある考え方に感謝します。
@ d-phは、次のことを意味します...「reflect」は以下のコードの関数ではないというエラーが表示されます。
また、エディターのインテリセンスでは、マッピング関数のプロパティp
がBluebirdのPromiseであり、Bluebirdでのみ見られる拡張APIサーフェス(Promiseではない)を持っていることを正しく識別しています。
私はそれから頭や尾を作ることができません。 マップのイテレータ変数の_type_を調べると、次のように表示されることに気付きました。
これが最終的にbluebird-global
定義された制限付きAPIサーフェスを取得する理由だと思いましたが、正しく解決されない理由はわかりません。
こんにちは。
再現できません:/これらのコードスニペットは私のセットアップで機能します。
初めに。 allSettled()
関数でbluebird-global
を使用していません。 Bluebird
を使用して直接入力します。 これは問題ではありませんが、おそらくあなたはそれに気づいていませんでした。 次のスニペットはbluebird-global
を使用しています:
function allSettled<T>(promises: Array<Promise<T>>) {
const reflections = Promise.all<T>(promises.map((promise => {
return promise.reflect();
})));
return reflections;
}
つまり、そのスニペットはグローバルPromise
( bluebird-global.d.ts
のBluebirdのメソッドでパッチが適用されています)にタイプします。 私が言ったように:これはあなたの情報のためのものです、あなたがそれを知らなかった場合に備えて、あなたと私のスニペットの両方が同じように機能するからです。
Bluebirdのメソッドが欠落しているという問題に戻ります。 私の推測では、実行時にグローバルPromise
をBluebirdに置き換えず、Bluebirdの代わりにグローバルPromiseを使用して構築されたPromisesでallSettled()
を実行します。
私のコードといくつかのスクリーンショットをお見せしましょう。
function allSettled<T>(promises: Array<Promise<T>>) {
const reflections = Promise.all<T>(promises.map((promise => {
return promise.reflect();
})));
return reflections;
}
let promises = [
Promise.resolve(),
Promise.reject(new Error("rejected test")),
new Promise<void>(() => {}),
];
let reflections = allSettled(promises);
console.log(reflections);
// this is part of my entry point
/*
* Promise
*/
import * as Promise from 'bluebird';
import 'expose-loader?Promise!bluebird';
_写真1:Array.map()の約束はBluebirdです( _bitField
のようなアンダースコアプロパティの存在によってわかります)_
_写真2:Promise.reflectは確かにループで定義されています_
Chrome Dev Toolsで私のようなjsブレークポイントを設定して、 .map
promise
を確認してください。 さらに良いことに、コンソールにPromise
と入力して、次の出力が得られるかどうかを確認できますか。
次の出力が得られた場合は、実行時にグローバルPromiseをBluebirdに置き換えていません。
その場合、あなたはそれをする必要があります。 たとえば、エントリファイルで私のように。
最後に、開発者からのフィードバックを少しだけ紹介します。個人的には、 Array<Promise<T>>
Promise<T>[]
を使用します。 しかし、これはもちろん開発者の好みによるものです。 テンプレートがなく、開発者が配列アクセス演算子を使用して型を定義するCのバックグラウンドから来ました。
乾杯。
このような徹底的な説明をありがとうございました。 しかし、私が確信していなかったことの1つは、次の点が何を指しているのかということでした。
import'expose-loader?Promise!bluebird ';
@ d-phああ、上の1つのライナーは私が欠けていたものでした。 あなたの助けがなければそこにたどり着くことはなかっただろう! 私だけかもしれませんが、 README
のテキストにExposeLoaderの使用への参照が含まれていると便利だと思います。
公平を期すために、これがwebpackの使用を必要とする場合、私はまだ100%ではありませんか? 私のターゲットはブラウザではなく、単なるノード関数です。
実際、ファイルを実行しようとすると次のエラーが発生するため、完全には機能していないように見えます(実行前にエディターにエラーはありません)。
エラー:モジュール 'expose-loader?Promise!bluebird'が見つかりません
そうです、 expose-loader
はwebpackのもの(webpackローダー)です。 したがって、webpackにそのimport
ステートメントを処理させないと、実行されません(つまり、「モジュールが見つかりません」というエラーが発生します)。
webpackを使用できない/使用しない場合は、実行時にグローバルPromiseをBluebirdにする別の方法を見つける必要があります。 私はノードの経験があまりありませんが、これを今見つけました:https://github.com/petkaantonov/bluebird/issues/1026(ノードのPromise
をオーバーライドします)。
最新のノード7でasync / awaitを使用する方法を見つけることをお勧めします。これが開発者に利用可能であるとき、あなたは幸運にも生きることができます。
READMEでexpose-loader
を使用することに言及することに関して:私はすでにd.ts
ファイルの先頭に、これは実行時にPromiseをBluebirdに置き換える開発者の仕事であると述べています: link 。 それを行う方法はたくさんあるので、実際にはそれらのどれにも言及しませんでした。 expose-loader
は、 window.Promise = Bluebird
を実行するのと同じであることに注意してください。 まあ、うまくいけば、グーグルが私の返信をインデックスに登録するので、人々はもう長い間可能なオプションを探すことはありません; p
@ d-phはネイティブのasync-awaitを楽しみにしていますが、これらの関数はすべてAWS Lambda上にあるため、今のところノード6.10.xにロックされています。 これらの関数の将来のパスでは、おそらくasync-awaitに切り替えて、TypescriptにES2015にトランスパイルさせますが、これはまだ導入したくありません。
とにかく、リンク@ d-phに感謝します、私はそのアプローチを試してみます。 ああ、そして誰かがこれらの関数の最終バージョンに興味がある場合(これはpromise-landで非常に便利です):
export function allSettled<T>(promises: Array<Promise<T>>) {
const reflections = Promise.all<Promise.Inspection<T>>( promises.map((p => p.reflect())) );
return reflections as Promise<Array<Promise.Inspection<T>>>;
}
export function settleProps<T>(promiseHash: IDictionary<Promise<T>>) {
const reflections: IDictionary<Promise<Promise.Inspection<T>>> = Object.keys(promiseHash)
.reduce((newObject: IDictionary<any>, key: string) => {
newObject[key] = promiseHash[key].reflect();
return newObject;
}, {} as IDictionary<Promise<Promise.Inspection<T>>>);
return Promise.props(reflections) as Promise<IDictionary<Promise.Inspection<T>>>;
}
完全なintelisync / type情報が利用可能であり、これは非常に優れています。
@ d-phうまくいけば、関連する質問でこれを復活させても大丈夫です...
bluebird-globalを使おうとすると、 then
とcatch
の両方で定義の違いが少しずつ出てきているようです。 これらはbluebird-globalで特別に処理されているようですが、bluebirdを取得するのではなく、標準のPromiseAPIに制限されているようです。 例えば:
Promise.resolve(true).catch(Error, () => false)
catch
は1つの引数しか期待しないため、失敗します。
そして別の問題:
Promise.resolve([3]).map((n: number) => true)
失敗する:
│TS2345: Argument of type '(n: number) => boolean' is not assignable to parameter of type 'IterateFunction<{}, boolean>'. │
│ Types of parameters 'n' and 'item' are incompatible. │
│ Type '{}' is not assignable to type 'number'. │
それらは機能する必要がありますか、それとも私は何か間違ったことをしていますか? これらは実行時に機能し、タイプチェックは行いません。
ありがとう!
こんにちは、
.catch(Error, function)
については、$ .then
、 .catch
(およびそれ以上)は他のBluebird関数とは異なる方法で処理されると言って間違いありません。 ただし、特定の.catch(Error, function)
オーバーライドはbluebird-globalに含まれています。 私は再確認し、コンパイルすることができます:
Promise.resolve(true).catch(Error, () => false)
TS3.0.1と2.9.2で確認しました。 ここで問題が発生する理由がわかりません。 bluebird-global
の後にグローバルPromiseをオーバーライドするTSプロジェクトに固有の何かがあるかもしれません。 わからない。 おそらく、非常に基本的なTSプロジェクトから始めて、現在のプロジェクトからさらに依存関係を追加することによって、問題の原因を絞り込み、どの時点で問題が発生するかを確認してください。
他の問題について:なぜそれが機能しないのかわかりません。 そして、はい、それは動作するはずです。 githubの問題を作成してください。そこから始めます。 問題に関するいくつかの事実は次のとおりです。
bluebird-global
が.map()
で行うことはすべて、$ bluebird.d.ts
の.map()
型定義を再利用することです。 言い換えれば、欠陥はbluebird-global
タイピングに起因するものであってはなりません。Promise.map()
で失敗しますが、 Bluebird.map()
で機能します:import Bluebird = require('bluebird');
Bluebird.resolve([3]).map((n: number) => true); // works
Promise.resolve([3]).map((n: number) => true); // fails
n
{}
であると結論付ける理由)、 bluebird.d.ts
も機能しないはずだと結論付けました。しかし、それは私にはわからない理由で機能します。 簡単に言うと、抽象化レイヤーをすべて削除した後、 .map()
が入力されるのは次のとおりです。map<U>(
mapper: (
item: U,
index: number,
arrayLength: number
) => U | PromiseLike<U>,
options?: Bluebird.ConcurrencyOption
): Bluebird<T extends Iterable<any> ? U[] : never>;
mapper
関数の戻り型は、$ item
の型と同じ(または同じPromise)である必要があることを示しています。 この例では、アイテムのタイプはnumber
で、返品タイプはboolean
です。 Bluebird
を直接使用すると、なぜこれがコンパイルされるのか理解できませんが、グローバルPromiseを使用するとコンパイルされません。 ちなみに、あなたの例のリターンタイプを任意の数に変更すると、それでも機能しません。 ただし、 item
はany
型である可能性があると言うと、機能します。 bluebird.d.ts
のtype IterableItem<R>
と、このコンテキストでの使用法に問題があります。
@ d-ph
編集:
map()
の「非レイヤー化」フォームをもう一度確認しましたが、 mapper
関数は、 item
のタイプと同じ戻りタイプを持つようにタイプされていません(私はそれを考えましただった)。 私の悪い。
bluebird-globalが.map()で行うことはすべて、bluebird.d.tsの.map()型定義を再利用するだけです。
ジェネリッククラスBluebird<R>
から型をコピーすると、親から推測できないため、デフォルトでR
の{}
になるという問題はありますか?
map: typeof Bluebird<T>.prototype.map
が機能するのだろうか? (私はまだこれを試していません)
重要:
@types/bluebird-global
を使用している場合は、@ d-phが言うように、依存関係@types/bluebird
を削除します
npm install --save-dev @types/bluebird-global
次に、タイピングに含まれている指示に従います:リンク(リンクは2017-04-02に更新されました)。 これだけでうまくいくはずです(つまり、手動でインポート/再割り当てする必要はありません)。補足として、
package.json::devDependencies
に@types/bluebird
を記載する必要はありません。これは、自動的に暗示されるためです。
両方があると、 @types/bluebird
と私のグローバルPromise( @types/bluebird-global
)によって返されるタイプ間の不一致が発生していました。
最も参考になるコメント
こんにちは、みんな、
@types/bluebird-global
が利用可能になりました。 これらのタイピングはボンネットの下で@types/bluebird@^3.0
を使用し、グローバルPromise
でbluebirdのメソッドを使用できるようにします(つまり、tsコンパイルは失敗しません)。使い方はこちらをお読みください。