JavaScript Promise API

7904 ワード

同期コードは追跡とデバッグが容易であるが、非同期コードは一般的に性能と柔軟性に優れている.Why「Hold up the show」when you can trigger numerous requests at once and then handle the m when each is ready?promiseと多くのプロミセに基づく新しいAPIはすでにJavaScriptの世界の重要な一部となっています.promiseのAPIはどうやって使うかを見てみましょう.
Promises in the Wild
XMLHttpRequest APIは非同期ですが、Promises APIは使用されていません.いくつかのnative APIはpromisesを使用しています.
  • Battery API
  • fetch API(XHRの代替)
  • ServiceWorker API(このAPIに関する記事は途中にある)
  • プロミセスが流行しますので、開発者たちは先端に行くべきです.疑いなく、Node.jsはpromisesのもう一つの重要なプラットフォームです.
    あなたが考えているよりもpromisesをテストしやすいです.setTimeoutはあなたの非同期の「タスク」をシミュレートすることができます.
    Baic Promise Usage
    コンストラクタnew Promise()は、setTimeoutまたはXMLHttpRequestのようなレガシーの非同期タスクにのみ使用されるべきである.newのキーワードとpromiseが提供するresolverejectのコールバック関数を使って、新しいpromiseを作成します.
    var p = new Promise(function(resolve, reject) {
        
        // Do an async task async task and then...
    
        if(/* good condition */) {
            resolve('Success!');
        }
        else {
            reject('Failure!');
        }
    });
    
    p.then(function() { 
        /* do something with the result */
    }).catch(function() {
        /* error :( */
    })
    
    非同期タスクの返却結果によれば、開発者は、コールバック関数の内部で手動でresolveまたはrejectを呼び出すことができる.XMLtHttpRequestをpromiseに基づくタスクに変換するのが現実的な例です.
    // From Jake Archibald's Promises and Back:
    // http://www.html5rocks.com/en/tutorials/es6/promises/#toc-promisifying-xmlhttprequest
    
    function get(url) {
      // Return a new promise.
      return new Promise(function(resolve, reject) {
        // Do the usual XHR stuff
        var req = new XMLHttpRequest();
        req.open('GET', url);
    
        req.onload = function() {
          // This is called even on 404 etc
          // so check the status
          if (req.status == 200) {
            // Resolve the promise with the response text
            resolve(req.response);
          }
          else {
            // Otherwise reject with the status text
            // which will hopefully be a meaningful error
            reject(Error(req.statusText));
          }
        };
    
        // Handle network errors
        req.onerror = function() {
          reject(Error("Network Error"));
        };
    
        // Make the request
        req.send();
      });
    }
    
    // Use it!
    get('story.json').then(function(response) {
      console.log("Success!", response);
    }, function(error) {
      console.error("Failed!", error);
    });
    
    Sometimes you don't need to complete an async task within the promise--if it's possible that an asynce will be taken,however,returning a promise will be best so that can always count on a promise funce.このようにすれば、Promise.resolve()またはPromise.reject()のキーワードを使用する必要なく簡単に呼び出すことができる.例を挙げて説明します
    var userCache = {};
    
    function getUserDetail(username) {
      // In both cases, cached or not, a promise will be returned
    
      if (userCache[username]) {
        // Return a promise without the "new" keyword
        return Promise.resolve(userCache[username]);
      }
    
      // Use the fetch API to get the information
      // fetch returns a promise
      return fetch('users/' + username + '.json')
        .then(function(result) {
          userCache[username] = result;
          return result;
        })
        .catch(function() {
          throw new Error('Could not find user: ' + username);
        });
    }
    
    上記の関数は常にプロミセオブジェクトに戻り、常にこの戻り値に対してnewまたはthen方法を使用することができる.
    then
    すべてのプロミスの例には、catch方法があり、このプロミセのインスタンスをさらに処理する.第1のthen方法のコールバック関数は、then方法における値を受信する.
    new Promise(function(resolve, reject) {
        // A mock async action using setTimeout
        setTimeout(function() { resolve(10); }, 3000);
    })
    .then(function(result) {
        console.log(result);
    });
    
    // From the console:
    // 10
    
    promiseがresolovedにされると、resolve()コールバック方法が起動されます.チェーンでthen方法を呼び出すこともできます.
    new Promise(function(resolve, reject) { 
        // A mock async action using setTimeout
        setTimeout(function() { resolve(10); }, 3000);
    })
    .then(function(num) { console.log('first then: ', num); return num * 2; })
    .then(function(num) { console.log('second then: ', num); return num * 2; })
    .then(function(num) { console.log('last then: ', num);});
    
    // From the console:
    // first then:  10
    // second then:  20
    // last then:  40
    
    then方法は、前のthen方法の戻り値を受信する.
    promiseがすでにresolovedに呼び出されている場合、thenの方法が呼び出された場合、コールバック関数は直ちに実行される.promiseがrejectiedされている場合、then方法はrejectionの後で、そのコールバック関数は永遠に実行されない.
    catch
    promiseがrejectiedされると、thenコールバック関数が実行される.
    new Promise(function(resolve, reject) {
        // A mock async action using setTimeout
        setTimeout(function() { reject('Done!'); }, 3000);
    })
    .then(function(e) { console.log('done', e); })
    .catch(function(e) { console.log('catch: ', e); });
    
    // From the console:
    // 'catch: Done!'
    
    catch方法で何を実行するかはあなた次第です.一般的なパターンは、rejectからErrorまでを送信する方法である.
    reject(Error('Data could not be found'));
    
    catchJavaScript loadersを考えてみてください.多くの非同期タスクが同時に触発されていますが、それらが全部完成した後に返事をしたいだけです.これがPromise.allの由来です.Promise.all方法はpromiseの配列に入ってきて、その後、それらの全てのresovedの後に、再度コールバック関数を出発する.
    Promise.all([promise1, promise2]).then(function(results) {
        // Both promises resolved
    })
    .catch(function(error) {
        // One or more promises was rejected
    });
    
    完璧な想像Promise.all方法の役割の例は、一度に複数のAJAXを出発することである(Promise.allを通じて).
    var request1 = fetch('/users.json');
    var request2 = fetch('/articles.json');
    
    Promise.all([request1, request2]).then(function(results) {
        // Both promises done!
    });
    
    全部promiseのAPIに戻ります.例えば、fetchとBattery API:
    Promise.all([fetch('/users.json'), navigator.getBattery()]).then(function(results) {
        // Both promises done!
    });
    
    もちろんrejectionを扱うのは難しいです.配列内の任意のプロミセがrejectiedされると、fetch方法がトリガされ、最初のrejectionが受信される.
    var req1 = new Promise(function(resolve, reject) { 
        // A mock async action using setTimeout
        setTimeout(function() { resolve('First!'); }, 4000);
    });
    var req2 = new Promise(function(resolve, reject) { 
        // A mock async action using setTimeout
        setTimeout(function() { reject('Second!'); }, 3000);
    });
    Promise.all([req1, req2]).then(function(results) {
        console.log('Then: ', one);
    }).catch(function(err) {
        console.log('Catch: ', err);
    });
    
    // From the console:
    // Catch: Second!
    
    catchPromise.raceは面白い方法です.すべてのプロミセがresovedまたはrejectにされるのを待つのではなく、行列の中にpromiseが一つある限り、reolvedまたはreject edされ、Promise.race方法がトリガされます.
    var req1 = new Promise(function(resolve, reject) { 
        // A mock async action using setTimeout
        setTimeout(function() { resolve('First!'); }, 8000);
    });
    var req2 = new Promise(function(resolve, reject) { 
        // A mock async action using setTimeout
        setTimeout(function() { resolve('Second!'); }, 3000);
    });
    Promise.race([req1, req2]).then(function(one) {
        console.log('Then: ', one);
    }).catch(function(one, two) {
        console.log('Catch: ', one);
    });
    
    // From the console:
    // Then: Second!
    
    有用な例は、第1のリソース要求と第2のリソース要求があるときにPromise.raceを使用することができることである.
    Get Used to Promises
    過去数年間、プロミスはずっとホットな話題でした.(もしあなたがDojo Toolkitユーザーだったら、過去の10年間になります.)今はプロミスはJavaScriptフレーム特性のレベルからJavaScript言語の特性になりました.あなたはAPIがますます多くなることを見ます.プロミセに基づいて実現することができます.これはいいことです.開発者たちは以前のcalback hellを避けることができ、非同期interactionsは他の変数のようにお互いに伝達することができます.プロミスは長い時間をかけて今の姿になりましたが、今はプロモーションを学ぶべき時です.
    JavaScript Promise APIより訳されます.