JavaScriptでthen()関数は何を意味しますか?


回答:


348

JavaScriptで非同期呼び出しを処理する従来の方法は、コールバックでした。アプリケーションを設定するために、サーバーに対して3つずつ呼び出しを行わなければならなかったとします。コールバックを使用すると、コードは次のようになります(サーバー呼び出しを行うxhrGET関数を想定)。

// Fetch some server configuration
    xhrGET('/api/server-config', function(config) {
        // Fetch the user information, if he's logged in
        xhrGET('/api/' + config.USER_END_POINT, function(user) {
            // Fetch the items for the user
            xhrGET('/api/' + user.id + '/items', function(items) {
                // Actually display the items here
            });
        });
    });

この例では、最初にサーバー構成をフェッチします。次に、それに基づいて、現在のユーザーに関する情報をフェッチし、最後に現在のユーザーのアイテムのリストを取得します。各xhrGET呼び出しは、サーバーが応答するときに実行されるコールバック関数を受け取ります。

もちろん、ネストのレベルが高くなるほど、コードの読み取り、デバッグ、保守、アップグレード、および基本的な操作が難しくなります。これは一般にコールバック地獄として知られています。また、エラーを処理する必要がある場合は、各xhrGET呼び出しに別の関数を渡して、エラーが発生したときに何をする必要があるかを通知する必要があります。共通のエラーハンドラを1つだけにする場合、それは不可能です。

Promise APIは、この入れ子の問題とエラー処理の問題を解決するために設計されました。

Promise APIは以下を提案します。

  1. 各非同期タスクはpromiseオブジェクトを返します。
  2. promiseオブジェクトにはthensuccess ハンドラーとerrorハンドラーという2つの引数を取る関数があります。
  3. 関数の成功またはエラーハンドラーは、非同期タスクが終了した後に1回thenだけ呼び出されます。
  4. このthen関数はも返し、promise複数の呼び出しをチェーンできるようにします。
  5. 各ハンドラー(成功またはエラー)はを返すことができvalue、これはargumentのチェーン内のとして次の関数に渡されpromiseます。
  6. ハンドラーがpromise(別の非同期要求を行う)を返す場合、次のハンドラー(成功またはエラー)は、その要求が完了した後でのみ呼び出されます。

したがって、前のコード例$httpは、promise とサービス(AngularJs)を使用して、次のようなものに変換できます。

$http.get('/api/server-config').then(
    function(configResponse) {
        return $http.get('/api/' + configResponse.data.USER_END_POINT);
    }
).then(
    function(userResponse) {
        return $http.get('/api/' + userResponse.data.id + '/items');
    }
).then(
    function(itemResponse) {
        // Display items here
    }, 
    function(error) {
        // Common error handling
    }
);

成功とエラーの伝播

プロミスの連鎖は非常に強力な手法であり、サービスがサーバーを呼び出し、データの後処理を行い、処理されたデータをコントローラーに返すなど、多くの機能を実現できます。ただし、 promiseチェーンを使用する場合は、いくつかの点に留意する必要があります。

次のpromise3つの約束、P1、P2、およびP3を持つ架空のチェーンを考えてみます。それぞれpromiseに成功ハンドラとエラーハンドラがあるため、P1にはS1とE1、P2にはS2とE2、P3にはS3とE3を使用します。

xhrCall()
  .then(S1, E1) //P1
  .then(S2, E2) //P2
  .then(S3, E3) //P3

エラーのない通常のフローでは、アプリケーションはS1、S2、最後にS3を通過します。しかし、実際には、物事はそれほどスムーズではありません。P1でエラーが発生するか、P2でエラーが発生してE1またはE2がトリガーされる可能性があります。

以下のケースを検討してください。

•P1のサーバーから正常な応答を受け取りましたが、返されたデータが正しくないか、サーバーに使用可能なデータがありません(空の配列と考えてください)。そのような場合、次のプロミスP2のために、エラーハンドラーE2をトリガーする必要があります。

•E2をトリガーするpromise P2のエラーを受け取ります。しかし、ハンドラー内にはキャッシュからのデータがあり、アプリケーションが通常どおりロードできることを保証します。その場合、E2の後にS3が呼び出されるようにする必要がある場合があります。

したがって、成功ハンドラまたはエラーハンドラを作成するたびに、呼び出しを行う必要があります。現在の関数を考えると、これはプロミスチェーンの次のハンドラの成功または失敗ですか。

チェーン内の次のpromiseの成功ハンドラーをトリガーする場合は、成功またはエラーハンドラーから値を返すだけです。

一方、チェーン内の次のpromiseのエラーハンドラーをトリガーする場合は、deferredオブジェクトを使用してそのreject()メソッドを呼び出すことで実行できます。

では、遅延オブジェクトとは何ですか?

jQueryの据え置きオブジェクトは、後で、通常は非同期に完了する作業単位を表します。作業単位が完了すると、deferredオブジェクトを解決または失敗に設定できます。

deferredオブジェクトが含まれているpromiseオブジェクトを。promiseオブジェクトを介して、作業単位が完了したときに何が起こるかを指定できます。そのためには、promiseオブジェクトにコールバック関数を設定します。

Jqueryの遅延オブジェクト:https ://api.jquery.com/jquery.deferred/

AngularJsの遅延オブジェクト:https : //docs.angularjs.org/api/ng/service/ $ q


3
とてもよく書かれています。これは私が本当に約束を明確にするのに役立ちました。
Ju66ernaut 2016

2番目のパラメーターであるエラーハンドラーは常にオプションですか?
1.21ギガワット2018年

これは私が今まで見た中で最高の答えです!
2018

78

then()関数は、jQueryやAngularJSなどの一部のライブラリまたはフレームワークで使用される「Javascript promise」に関連しています。

promiseは、非同期操作を処理するためのパターンです。promiseを使用すると、コールバックとして使用する関数を指定できる「then」というメソッドを呼び出すことができます。

詳細については、http//wildermuth.com/2013/8/3/JavaScript_Promisesを参照してください。

Angular promisesの場合:http : //liamkaufman.com/blog/2013/09/09/using-angularjs-promises/


4
タスクの完了時に実行されるコールバックのようなものですか?違いは

3
他のコメントのJavaScriptの約束は、次のように述べています:A promise can only succeed or fail onceIf a promise has succeeded or failed and you later add a success/failure callback, the correct callback will be called
Xiao

また、Promiseナゲットは、使用方法promiseと何が行われるかを説明していますcallback
Xiao

最初のページには、欠けているコードのチャンクがあります(大きな白い空白)。ほとんどの人は要素を調べることを考え、その下にあるバイオリンのURLを見つけます。このメッセージは残りの部分のためのものです-フィドルはまだ機能しています;)
DanteTheSmith

1
@MuhammadUmer:この読みstackoverflow.com/a/31453579/1350476(シドによって答えを)
SharpCoder

32

私の知る限り、(この記事の執筆時点では)組み込みのthen()メソッドはありませんjavascript

それが何であれそれはように見えるdoSome("task")というメソッドを持って戻っていますthen

の戻り結果をdoSome()コンソールに記録すると、戻された内容のプロパティを確認できるはずです。

console.log( myObj.doSome("task") ); // Expand the returned object in the
                                     //   console to see its properties.

更新(ECMAScript6以降):-

この.then()関数は純粋なJavaScriptに含まれています。

こちらのMozillaドキュメントから

then()メソッドはPromiseを返します。これは2つの引数を取ります。Promiseの成功と失敗の場合のコールバック関数です。

次に、Promiseオブジェクトは次のように定義されます。

Promiseオブジェクトは、遅延計算と非同期計算に使用されます。Promiseは、まだ完了していないが、将来予定されている操作を表します。

つまり、は、Promiseまだ計算されていないが将来解決される値のプレースホルダーとして機能します。そして、この.then()関数は、Promiseが解決されたときに呼び出される関数を、成功または失敗として関連付けるために使用されます。


12
組み込みはありませんでした.thenが、ネイティブプロミスがES6で現在提供されています:html5rocks.com/en/tutorials/es6/promises
janfoeh 2013

この答えをありがとう、私はいくつかのクールなpromiseコールバックを期待していましたが、返された 'then'という実際の関数であることが判明しました。
スパルティク2016年

15

これは、物事がどのように機能するかを明らかにするために私が自分で作ったものです。他の人もこの具体的な例が役立つと思うでしょう:

doit().then(function() { log('Now finally done!') });
log('---- But notice where this ends up!');

// For pedagogical reasons I originally wrote the following doit()-function so that 
// it was clear that it is a promise. That way wasn't really a normal way to do 
// it though, and therefore Slikts edited my answer. I therefore now want to remind 
// you here that the return value of the following function is a promise, because 
// it is an async function (every async function returns a promise). 
async function doit() {
  log('Calling someTimeConsumingThing');
  await someTimeConsumingThing();
  log('Ready with someTimeConsumingThing');
}

function someTimeConsumingThing() {
  return new Promise(function(resolve,reject) {
    setTimeout(resolve, 2000);
  })
}

function log(txt) {
  document.getElementById('msg').innerHTML += txt + '<br>'
}
<div id='msg'></div>


5

ここに小さなJS_Fiddleがあります。

次に、promiseが解決された後に使用できるメソッドコールバックスタックです。jQueryのようなライブラリの一部ですが、ネイティブJavaScriptで使用できるようになり、以下にその動作の詳細な説明を示します

ネイティブJavaScriptでPromiseを実行できます。jQueryにPromiseがあるのと同じように、すべてのPromiseをスタックして、ResolveおよびRejectコールバックで呼び出すことができます。これが非同期呼び出しをチェーンする方法です。

バッテリーの充電状態について、MSDNドキュメントから分岐して編集しました。

これは、ユーザーのラップトップまたはデバイスがバッテリーを充電しているかどうかを調べることです。次に呼び出され、あなたは成功後に仕事をすることができます。

navigator
    .getBattery()
    .then(function(battery) {
       var charging = battery.charging;
       alert(charging);
    })
    .then(function(){alert("YeoMan : SINGH is King !!");});

別のes6の例

function fetchAsync (url, timeout, onData, onError) {
    
}
let fetchPromised = (url, timeout) => {
    return new Promise((resolve, reject) => {
        fetchAsync(url, timeout, resolve, reject)
    })
}
Promise.all([
    fetchPromised("http://backend/foo.txt", 500),
    fetchPromised("http://backend/bar.txt", 500),
    fetchPromised("http://backend/baz.txt", 500)
]).then((data) => {
    let [ foo, bar, baz ] = data
    console.log(`success: foo=${foo} bar=${bar} baz=${baz}`)
}, (err) => {
    console.log(`error: ${err}`)
})

定義:: 次に、非同期コールバックを解決するために使用されるメソッドです

これはES6で導入されました

ここで適切なドキュメントを見つけてくださいEs6 Promises


あなたの答えは実際には質問に答えるものではありません。どこthenから来てどのように機能するかを説明せずに、APIの使用例を提供するだけです。これらの詳細を提供するには、回答を改善する必要があります。
Didier L

@TarandeepSingh-バッテリーの状態を警告する最初のthenステートメントでは、promiseオブジェクトは返されません。次に、2番目の使用法は何
ですか

@MohitJainこれは、新しい約束がない場合でも、複数のコールバックを実行できることを示しています。それ以来、Promise.allを使用して複数の呼び出しを行うこともできます。
Tarandeep Singh

メソッドコールバックスタック」とはどういう意味ですか?
ベルギ

4

doSomeがこれを返すのではないかと思います。これは、thenメソッドを持つmyObjです。標準メソッドの連鎖...

doSomeがこれを返さない場合、つまりdoSomeが実行されたオブジェクトである場合は、thenメソッドを使用してオブジェクトが返されることを確認してください...

@patrickが指摘するように、標準のjsにはthen()はありません


1
私はdoSomeがこれを返すと思います -そのような疑惑を強制/正当化するものは何もありません
SalathielGenèse2018

1

doSome( "task")はpromiseオブジェクトを返す必要があり、そのpromiseは常にthen関数を持っているため、コードは次のようになります

promise.then(function(env) {
    // logic
}); 

これは、メンバー関数の通常の呼び出しにすぎません。


1

.then 非同期関数でpromiseを返します。

良い例は:

var doSome = new Promise(function(resolve, reject){
    resolve('I am doing something');
});

doSome.then(function(value){
    console.log(value);
});

別のロジックを追加するにreject('I am the rejected param')は、関数の呼び出しとconsole.logを追加することもできます。


0

この場合then()、メソッドによって返されるオブジェクトのクラスメソッドですdoSome()


0

「.then()」関数は、Windows 8ストアアプリの非同期プログラミングで約束されたオブジェクトに広く使用されています。私が理解している限り、コールバックのように機能します。

このドキュメンテーションで詳細を検索 http://msdn.microsoft.com/en-us/library/windows/apps/hh700330.aspx

原因としては、他の定義済み関数の名前になることもあります。


0

もう一つの例:

new Promise(function(ok) {
   ok( 
      /* myFunc1(param1, param2, ..) */
   )
}).then(function(){
     /* myFunc1 succeed */
     /* Launch something else */
     /* console.log(whateverparam1) */
     /* myFunc2(whateverparam1, otherparam, ..) */
}).then(function(){
     /* myFunc2 succeed */
     /* Launch something else */
     /* myFunc3(whatever38, ..) */
})

矢印関数の略記を使用した同じロジック:

new Promise((ok) =>
   ok( 
      /* myFunc1(param1, param2, ..) */
)).then(() =>
     /* myFunc1 succeed */
     /* Launch something else */
     /* Only ONE call or statment can be made inside arrow functions */
     /* For example, using console.log here will break everything */
     /* myFunc2(whateverparam1, otherparam, ..) */
).then(() =>
     /* myFunc2 succeed */
     /* Launch something else */
     /* Only ONE call or statment can be made inside arrow functions */
     /* For example, using console.log here will break everything */
     /* myFunc3(whatever38, ..) */
)


-4

私は約8年遅れています。ええと、とにかく、then()が何をするのか本当にわかりませんが、MDNが答えを持っているかもしれません。実際、もう少し理解できるかもしれません。

これにより、必要なすべての情報が(うまくいけば)表示されます。誰かがこのリンクをすでに投稿していない限り。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then

形式はpromise.prototype.then()です。promiseとプロトタイプは、JavaScriptの変数のようなものではなく、変数のようなものです。つまり、他のものがnavigator.getBattery()。then()のように、実際に存在しますが、 Webではほとんど使用されていませんが、これはデバイスのバッテリーのステータスを表示します。知りたい場合は、MDNの詳細情報を表示します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.