[解決済み] JavaScript の Promise が解決するのを待ってから機能を再開するにはどうすればよいですか?
質問
ユニットテストを行っています。テストフレームワークは、ページをiFrameにロードし、そのページに対してアサーションを実行します。 各テストが始まる前に、私は
Promise
を設定し、iFrameの
onload
イベントを呼び出して
resolve()
を設定すると、iFrameの
src
そしてプロミスを返します。
ということで、そのまま
loadUrl(url).then(myFunc)
を実行する前に、ページが読み込まれるのを待ちます。
myFunc
があります。
私はこの種のパターンをテストのいたるところで使っています (URL を読み込むためだけではなく)、主に DOM への変更を可能にするためです (たとえば、ボタンをクリックするのを真似たり、div が隠れたり現れたりするのを待ったりします)。
この設計の欠点は、数行のコードを含む匿名関数を常に書いていることです。 さらに、回避策もあるのですが(QUnitの
assert.async()
)、プロミスを定義するテスト関数は、プロミスが実行される前に完了します。
の値を取得する方法はないのでしょうか?
Promise
のように、解決するまで待つ(ブロック/スリープ)ことができます。
IAsyncResult.WaitHandle.WaitOne()
. JavaScriptがシングルスレッドであることは知っていますが、だからといって関数が降伏できないとは限らないと思っています。
要するに、以下のように正しい順序で結果を吐き出させる方法はないのでしょうか?
function kickOff() {
return new Promise(function(resolve, reject) {
$("#output").append("start");
setTimeout(function() {
resolve();
}, 1000);
}).then(function() {
$("#output").append(" middle");
return " end";
});
};
function getResultFrom(promise) {
// todo
return " end";
}
var promise = kickOff();
var result = getResultFrom(promise);
$("#output").append(result);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="output"></div>
解決方法は?
<ブロッククオートプロミスから値を取得する方法や、プロミスから値を取得する方法はないでしょうか? が解決するまで待つ(ブロック/スリープ)。 IAsyncResult.WaitHandle.WaitOne()。JavaScriptが シングルスレッドですが、だからといって、関数が は降伏できない。
現世代のブラウザに搭載されているJavascriptには
wait()
または
sleep()
他のものを実行することができます。 ですから、単純にあなたが求めていることはできないのです。 その代わり、非同期オペレーションがあり、それが完了したらあなたを呼び出します(あなたがプロミスを使用していたように)。
その理由のひとつは、Javascriptがシングルスレッドであることです。 シングルスレッドが回転している場合、その回転しているスレッドが終了するまで、他のJavascriptを実行することはできません。 ES6では
yield
とジェネレータを使うことで、このような協力なトリックが可能になりますが、インストールされているブラウザの広い範囲でこれらを使えるようになるには、まだかなり時間がかかります(使用するJSエンジンを制御するサーバーサイド開発では使用可能です)。
プロミス・ベースのコードを注意深く管理することで、多くの非同期処理の実行順序を制御することができます。
あなたのコードで実現しようとしている順序を正確に理解しているわけではありませんが、あなたの既存の
kickOff()
関数を使用し、その後に
.then()
ハンドラを呼び出した後、そのハンドラに
function kickOff() {
return new Promise(function(resolve, reject) {
$("#output").append("start");
setTimeout(function() {
resolve();
}, 1000);
}).then(function() {
$("#output").append(" middle");
return " end";
});
}
kickOff().then(function(result) {
// use the result here
$("#output").append(result);
});
これは、保証された順序で出力を返します - このように。
start
middle
end
2018年(この回答が書かれてから3年後)のアップデート。
コードをトランスパイルするか、以下のような ES7 の機能をサポートする環境でコードを実行する場合。
async
と
await
を使用することができるようになりました。
await
を使えば、プロミスの結果を待っているように見せることができます。 これはまだプロミスを使ったプログラミングです。 これはまだJavascriptのすべてをブロックするものではありませんが、より親しみやすい構文でシーケンシャルな操作を書くことができるようになります。
ES6のやり方の代わりに。
someFunc().then(someFunc2).then(result => {
// process result here
}).catch(err => {
// process error here
});
こんなことができるんですね。
// returns a promise
async function wrapperFunc() {
try {
let r1 = await someFunc();
let r2 = await someFunc2(r1);
// now process r2
return someValue; // this will be the resolved value of the returned promise
} catch(e) {
console.log(e);
throw e; // let caller know the promise was rejected with this reason
}
}
wrapperFunc().then(result => {
// got final result
}).catch(err => {
// got error
});
async
関数は、最初の
await
は関数本体の中でヒットするので、呼び出し側にとって非同期関数はまだノンブロッキングであり、呼び出し側はまだ返されたプロミスを処理してそのプロミスから結果を取得しなければなりません。 しかし
async
を使用すると、よりシーケンシャルなコードを書くことができます。
await
約束について 心に留めておいてください
await
はプロミスを待っている間だけ役に立つことをします。
async/await
非同期処理はすべてプロミスベースでなければなりません。
関連
-
[解決済み】Angular JS Uncaught Error。[インジェクター:モジュラー]。
-
[解決済み] 解決済み】clearInterval()が動作しない [重複] [重複]
-
[解決済み】JavaScriptで関数が存在するかどうかを確認する方法は?
-
[解決済み] JavaScriptで文字列が部分文字列を含むかどうかを確認する方法は?
-
[解決済み] あるJavaScriptファイルを他のJavaScriptファイルにインクルードするにはどうすればよいですか?
-
[解決済み] JavaScriptでメールアドレスを検証するのに最適な方法は何ですか?
-
[解決済み] JavaScriptでタイムスタンプを取得する方法は?
-
[解決済み] JavaScriptのオブジェクトが空であることをテストするにはどうすればよいですか?
-
[解決済み】JavaScriptで文字列の出現箇所をすべて置換する方法
-
[解決済み】オブジェクトからプロパティを削除する(JavaScript)
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Javascript:getElementById対getElementsById(両方が別のページで動作する)。
-
[解決済み】TypeError: 'undefined'はオブジェクトではありません。
-
[解決済み】ある要素が可視DOMに存在するかどうかを確認するにはどうすればいいですか?
-
[解決済み】ある要素を別の要素に移動させるには?
-
[解決済み】WebpackとBabelで「このファイルタイプを扱うには適切なローダーが必要な場合があります。
-
[解決済み】SyntaxError: JSON の位置 1 に予期しないトークン o があります。
-
[解決済み] ローカルファイルを開くことができません - Chrome: ローカルリソースのロードが許可されていません
-
[解決済み】React-Routerの子が1つしかない。
-
[解決済み】このオブジェクトの "forEach "はなぜ関数でないのですか?
-
[解決済み】Vueが定義されていない