私は、Promise の配列に対して for ループを使用する正しい方法を理解しようと努めてきました。私のコードでは、配列に 3 つの要素がありますが、データがあるのはループの初回のみです。
private populateRequest(connection: Connection, myArray: any[], containerId: string): Promise<void> {
// tslint:disable-next-line:no-shadowed-variable
return new Promise(async (resolve, reject) => {
const promises: Array<Promise<SomeType>> = [];
let status = '';
// tslint:disable-next-line:prefer-for-of
for (let i = 0; i < myArray.length; i++) {
const data = await this.getResolvedPromise(myArray[i])
.then(response => response)
.catch(err => console.log(err));
if (this.flags.hasOwnProperty('prop1')) {
status = 'Active';
} else if (this.flags.hasOwnProperty('prop2')) {
status = 'Inactive';
} else if (data[0]['WidgetProp1'] === 'Active') {
status = 'Inactive';
} else if (data[0]['WidgetProp1'] === 'Inactive') {
status = 'Active';
}
const myMetaObj = {
prop3: data[0]['WidgetProp3'],
status
};
const myMetaMember = {
ContainerId: containerId,
ContentEntityId: data[0]['WidgetId'],
Body: data[0]['WidgetBody'],
Metadata: myMetaObj
};
promises.push(myMetaMember);
}
Promise.all(promises)
.then(() => resolve())
.catch(err => reject(err));
});
}
private getResolvedPromise(target: Promise<any>): Promise<any> {
// tslint:disable-next-line:no-any
return new Promise((resolve, reject) => {
// tslint:disable-next-line:no-any
Promise.all([target])
.then(() => resolve(target))
.catch(err => reject(err));
});
}
プッシュは最初は意図したとおりに機能しますが、それ以降は機能しません。
これは非同期コードと呼び出しが完了していないことが原因であることは理解していますが、Promise.all() が正しく動作しない理由がわかりません。
ハルプス?
ここには多くの間違った点がありますが、これを書き直そうとするとき、トリガー配列に何が入っているのかを知る必要があります。そして、myArray 配列には何が入っているのでしょうか?そこにはどのような種類のデータが含まれていますか?そして、その配列から取得したデータに対して getResolvedPromise() を使って何をしようとしているのでしょうか?
– jfriend002020 年 9 月 4 日 23:09
triggers は myArray であるはずで、これには 3 つの解決された Promise が含まれています。これらにはすべて、コードの残りの部分で使用する必要がある約 5 つのプロパティがあります。このデータは最終的に SaaS API に送信されます。解決された約束しか得られません。なぜなら、約束を理解しようとして、解決できないと思ったからです。Promise オブジェクトを返す関数が必要でした。必要な 3 つはすでにあるので、解決された Promise の取得を破棄して、他のものと同様にプロパティによってオブジェクトにアクセスするだけでよいでしょうか?
– トレブルコード2020 年 9 月 4 日 23:14
1
また、getResolvePromise() は何も役に立たないようです。 Promise.all([target]) を呼び出して、target に解決される Promise を返します。それは何も有益なことを達成していないようです。どう思いましたか帽子は達成していました。つまり、target があり、target を解決する Promise ができました。ターゲットが Promise だった場合でも、getResolvePromise() の呼び出し元は、その呼び出しから結果を取得するために await または .then() を使用する必要があります。
– jfriend002020 年 9 月 4 日 23:14
関数への入力が何であるか、必要な出力が何であるかをバックアップして説明してください。おそらくそれを実現する書き換えを示すことができます。現時点では、どのようなデータが入ってきて、どのようなデータを送り出したいのか、混乱していますか?
– jfriend002020 年 9 月 4 日 23:15
1
それでは、populateRequest() は何を返す、または何をするのでしょうか?
– jfriend002020 年 9 月 4 日 23:25
ここにはいくつか間違った点があります。
まず、Promise 変数に Promise をプッシュしているわけではありません。 myMetaMember 変数をその配列にプッシュしています。
第 2 に、すでに await を使用して非同期リクエストをシリアル化している場合は、Promise.all() を使用する必要はまったくありません。
Tなるほど、必要がないときに手動で作成した Promise の追加レイヤーで既存の Promise をラップするという、いくつかのアンチパターンを使用しています。
第 4 に、通常、await と .then() および .catch() を混合したくないです。 await からのエラーをキャッチするには、try/catch を使用します。 await がすでに値を取得しているため、.then() は必要ありません。
第 5 に、getResolvePromise() は何も役に立たないようです。 Promise.all([target]) を呼び出して、target に解決される Promise を返します。それは何も有益なことを達成しているようには見えません。それによって何が達成されたと思いますか。
myArray が、それぞれの結果がオブジェクトになる Promise の配列であることが明らかになったので、ここでは、あなたがやろうとしていることについての私なりの最善の解釈を示します。
private populateRequest(connection: Connection, myArray: any[], containerId: string): Promise<Array<{ContainerId: string; ContentEntityId: unknown; Body: unknown; Metadata: {prop3: unknown; status: string}}>> {
return Promise.all(myArray).then(results => {
return results.map(data => {
let status = '';
if (this.flags.hasOwnProperty('prop1')) {
status = 'Active';
} else if (this.flags.hasOwnProperty('prop2')) {
status = 'Inactive';
} else if (data[0]['WidgetProp1'] === 'Active') {
status = 'Inactive';
} else if (data[0]['WidgetProp1'] === 'Inactive') {
status = 'Active';
}
const myMetaObj = {
prop3: data[0]['WidgetProp3'],
status
};
const myMetaMember = {
ContainerId: containerId,
ContentEntityId: data[0]['WidgetId'],
Body: data[0]['WidgetBody'],
Metadata: myMetaObj
};
return myMetaMember;
});
});
}
r を取得するにはmyArray からの結果 (それぞれがオブジェクトに解決される配列または Promise であると言った場合は、 Promise.all(myArray) を使用します。これにより、結果の配列に解決される単一の Promise が返され、それを使用できます。 ) 結果の配列を取得します。その後、その配列を反復して、データに基づいて新しいオブジェクトを構築できます。
追記myArray が実際に Promise の配列である場合は、それを myArray: any[] として宣言すべきではありません。これは、TypeScript が読者 (私) にそれが何であるかを教えず、正しいものが渡されることを TypeScript に強制させないという点で、TypeScript の理由の一部を無効にします。
2020 年 9 月 4 日 23:30 に回答
jfriend00jfriend00
692,000
99
金バッジ 99 個
1002
銀バッジ 1002 個
銅バッジ 992 個
銅バッジ 992 個
5
@jfriend00、ありがとうございます。その説明は非常に明確です。これを回答としてマークします
– トレブルコード2020 年 9 月 4 日 23:31
TypeScript に関しては、Promise<void> Promise<{…}[]> に変更する必要があります。メタメンバーのオブジェクト タイプを使用します。
– ベルギ2020 年 9 月 4 日 23:34
@Bergi - TypeScript らしさを修正/改善するための編集を提案してください (または回答を自分で編集してください)。
– jfriend002020 年 9 月 4 日 23:36
@jfriend00 編集を提案する方法がわからない場合は、 [保存]をクリックすると、そのまま保存されます。
– ベルギ2020 年 9 月 4 日 23:42
@Bergi - そうですね、あなたには編集のスーパーパワーがあるので、編集はそのまま適用されます。そうですね。
– jfriend002020 年 9 月 4 日 23:53
あなたの例は本当に理解できません。でも私が見ているのは、あなたあなたは getResolvedPromise からの Promise を同期的に解決する await を使用しています。また、 .then を await と組み合わせて使用していますが、これは同じことを行うため意味がありませんが、「await」として別のスタイルで使用しているだけです。したがって、次のいずれかを実行します。
const data = await promise;
// data is resolved here
または
promise.then(
data => // data is resolved here
)
.map を使用する代わりに for ループを使用して構造を反復する必要がある場合は、次のようなことを行うことをお勧めします。
async someFunction(): Promise<any[]> {
promises: Promise<any>[] = []
for(const value of list) {
promises.push(new Promise((resolve, reject) => {
const data = await something
// do something with data
const fancyObject = {}
resolve(fancyObject);
}));
return Promise.all(promises);
}
データ オブジェクトに依存するロジックは、await 演算子を介して Promise が解決された後にのみ実行されることがわかります。したがって、このロジックは Promise 自体でラップする必要があります。
Promise.all 自体は Promise を返すため、別の Promise でラップする必要はなく、すべての fancyObject を含む配列に解決されます。 await 構文には try catch ブロックが必要であることにも注意してください。Promise の解決中に発生するエラーを捕捉するため。
私があなたの話を正しく理解し、私の例を何かに応用できることを願っています。
6
はい、これは理にかなっています。@leonat に感謝します。考えてみるととても楽しかったです。
– トレブルコード2020 年 9 月 4 日 23:23
私たちはここにいるのでここでの実際のデータと関数が何を行うべきかを理解するには、OP と積極的に連携する必要があります。問題の一部についてコメントを提供するよりも、それが明確になるまで待った方がよいでしょう。また、OP に明確な質問を書いてもらい、明確な回答を書けるように努めています (これにより、StackOverflow がより便利な場所になります)。
– jfriend002020 年 9 月 4 日 23:24
問題は、await と .then() をよりよく理解する必要があることと、まったく必要のない機能です。
– トレブルコード2020 年 9 月 4 日 23:27
私が回答を書いたとき、あなたのコメントは存在しませんでした。 stackoverflow 応答を扱うのはこれが初めてなので、応答プロセスがどのように機能するかを理解する必要があります。答える前に質問を明確にすることは理にかなっています。次回はそうします。それでも私は、全体の混乱は、Promise がどのように機能するかについての誤解から生じたと思います。そのため、for ループで Promise を操作する方法についての最低限のテンプレートを提供しました。
– レオナット2020 年 9 月 4 日 23:29
問題ありません。あなたはただ助けようとしただけのようですね (それは良いことです)。
– jfriend002020 年 9 月 4 日 23:33