フロントエンド神器--プロミス

13538 ワード

 
  

 
   

Promise in js

回调函数真正的问题在于他剥夺了我们使用 return 和 throw 这些关键字的能力。而 Promise 很好地解决了这一切。

2015 年 6 月,ECMAScript 6 的正式版 终于发布了。

ECMAScript 是 JavaScript 语言的国际标准,JavaScript 是 ECMAScript 的实现。ES6 的目标,是使得 JavaScript 语言可以用来编写大型的复杂的应用程序,成为企业级开发语言。

概念

ES6 原生提供了 Promise 对象。

所谓 Promise,就是一个对象,用来传递异步操作的消息。它代表了某个未来才会知道结果的事件(通常是一个异步操作),并且这个事件提供统一的 API,可供进一步处理。

Promise 对象有以下两个特点。

(1)对象的状态不受外界影响。Promise 对象代表一个异步操作,有三种状态:Pending(进行中)、Resolved(已完成,又称 Fulfilled)和 Rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是 Promise 这个名字的由来,它的英语意思就是「承诺」,表示其他手段无法改变。

(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise 对象的状态改变,只有两种可能:从 Pending 变为 Resolved 和从 Pending 变为 Rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。就算改变已经发生了,你再对 Promise 对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

有了 Promise 对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise 对象提供统一的接口,使得控制异步操作更加容易。

Promise 也有一些缺点。首先,无法取消 Promise,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部。第三,当处于 Pending 状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。

var promise = new Promise(function(resolve, reject) {
 if (/*        */){
 resolve(value);
 } else {
 reject(error);
 }
});

promise.then(function(value) {
 // success
}, function(value) {
 // failure
});
Promiseコンストラクタはパラメータとして関数を受け入れ,この関数の二つのパラメータはそれぞれreolve法とreject法である.
非同期操作が成功すれば、レシオ方式でPromiseオブジェクトの状態を「未完成」から「成功」に変えます.
非同期操作が失敗したら、プロジェクト方法でPromiseオブジェクトの状態を「未完成」から「失敗」に変更します.
基本的なアプリ
  • Promise.resove()
  • Promise.reject()
  • Promise.prototype.then()
  • Promise.prototype.ctch()
  • Promise.all()/すべての完了
    var p = Promise.all([p1,p2,p3]);
    
  • Promise.race()/競速は、一つで
  • です.
    階段を進める
    promisesの奇妙さは以前のreturnとthrowを与えてくれます.各Promiseはthen関数とcatch()を提供します.実際にはthen(null,...)関数です.
        somePromise().then(functoin(){
            // do something
        });
    
    
    私たちは3つのことができます.1.returnもう1つのpromise 2.returnの同期の値(またはundefined)3.throw同期異常throw new Eror('');1.パッケージ同期と非同期コード
    ```
    new Promise(function (resolve, reject) {
    resolve(someValue);
    });
    ```
      
    
    ```
    Promise.resolve(someValue);
    ```
    
    2.捕獲同期異常
     new Promise(function (resolve, reject) {
     throw new Error('   ,   bug  ');
     }).catch(function(err){
     console.log(err);
     });
    
    同期コードであれば、作成できます.
        Promise.reject(new Error("   "));
    
    
    3.複数の異常捕獲、より正確な捕獲
    somePromise.then(function() {
     return a.b.c.d();
    }).catch(TypeError, function(e) {
     //If a is defined, will end up here because
     //it is a type error to reference property of undefined
    }).catch(ReferenceError, function(e) {
     //Will end up here if a wasn't defined at all
    }).catch(function(e) {
     //Generic catch-the rest, error wasn't TypeError nor
     //ReferenceError
    });
    
    4.2つのPromiseの戻り値を取得する
    1. .then       
    2.          
    3. spread
    
    5.finally
              ,     catch   
    
    6.bind
    somethingAsync().bind({})
    .spread(function (aValue, bValue) {
     this.aValue = aValue;
     this.bValue = bValue;
     return somethingElseAsync(aValue, bValue);
    })
    .then(function (cValue) {
        return this.aValue + this.bValue + cValue;
    });
    
    あるいはあなたもこのようにすることができます.
    var scope = {};
    somethingAsync()
    .spread(function (aValue, bValue) {
     scope.aValue = aValue;
     scope.bValue = bValue;
     return somethingElseAsync(aValue, bValue);
    })
    .then(function (cValue) {
     return scope.aValue + scope.bValue + cValue;
    });
    
    しかし、これは非常に多くの違いがあります.
  • 資源の浪費とメモリ流出のリスクがあると先に宣言しなければなりません.
  • は、表現の文脈においては使用できません.
  • 効率が低い
  • .
    7.all.非常にダイナミックなサイズの均一なPromiseリストを処理するために使用されます.
    8.ジョン.複数の分離を扱うPromiseに最適です.
    ```
    var join = Promise.join;
    join(getPictures(), getComments(), getTweets(),
    function(pictures, comments, tweets) {
    console.log("in total: " + pictures.length + comments.length + tweets.length);
    });
    ```
    
    9.props.プロミセのmap集合を処理します.失敗が一つだけあります.すべての実行が終わります.
    ```
    Promise.props({
    pictures: getPictures(),
    comments: getComments(),
    tweets: getTweets()
    }).then(function(result) {
    console.log(result.tweets, result.pictures, result.comments);
    });
    ```
    
    10.any、some、race
    ```
    Promise.some([
    ping("ns1.example.com"),
    ping("ns2.example.com"),
    ping("ns3.example.com"),
    ping("ns4.example.com")
    ], 2).spread(function(first, second) {
    console.log(first, second);
    }).catch(AggregateError, function(err) {
    
    err.forEach(function(e){consolie.error(e.stack)};可能性があります.失敗のpromiseが多いため、Promsieは永遠にfulfilledできません.
    11.map(Function mapper[,Object options])
            ,   promise   ,
    
    Option:concurrencyそして発見
        map(..., {concurrency: 1});
    
    以下は合併数量を制限しないで、読書文書の情報です.
    var Promise = require("bluebird");
    var join = Promise.join;
    var fs = Promise.promisifyAll(require("fs"));
    var concurrency = parseFloat(process.argv[2] || "Infinity");
    
    var fileNames = ["file1.json", "file2.json"];
    Promise.map(fileNames, function(fileName) {
     return fs.readFileAsync(fileName)
     .then(JSON.parse)
     .catch(SyntaxError, function(e) {
     e.fileName = fileName;
     throw e;
     })
    }, {concurrency: concurrency}).then(function(parsedJSONs) {
     console.log(parsedJSONs);
    }).catch(SyntaxError, function(e) {
     console.log("Invalid JSON in file " + e.fileName + ": " + e.message);
    });
    
    結果
    $ sync && echo 3 > /proc/sys/vm/drop_caches
    $ node test.js 1
    reading files 35ms
    $ sync && echo 3 > /proc/sys/vm/drop_caches
    $ node test.js Infinity
    reading files: 9ms
    
    11.reduce(Function reducer[,dynamic initial Value])->Promise
    Promise.reduce(["file1.txt", "file2.txt", "file3.txt"], function(total, fileName) {
     return fs.readFileAsync(fileName, "utf8").then(function(contents) {
     return total + parseInt(contents, 10);
     });
    }, 0).then(function(total) {
     //Total is 30
    });
    
    12.Time
  • .delay(int ms)->Promise
  • .timeout(int ms[,String message]]]->Promise
  • Promiseの実現
  • q
  • ブルーバード
  • co
  • when
  • ASYNC
    async関数はPromise、Generator関数と同じで、コールバック関数の代わりに、非同期動作を解決する方法です.本質的にはGenerator関数のシンタックス飴です.async関数はES 6ではなく、ES 7に含まれています.
    参考文献(書き写してもいいという):
    阮一峰のES 6教程はpromisesについてどれぐらい理解しましたか?Bluebirdの公式文書
    流星の暴走
    リンク:http://www.jianshu.com/p/063f7e490e9a
    ソース:略書
    著作権は作者の所有に帰する.商業転載は作者に連絡して授権を獲得してください.商業転載ではないので、出典を明記してください.ise in js
    コールバック関数の真の問題は、彼が私たちにreturnとthrowというキーワードを使用する能力を奪われたことにある.Promiseはこのすべてをうまく解決しました.
    2015年6月、ECMAScript 6の正式版がついに発表されました.
    ECMAScriptはJavaScript言語の国際標準であり、JavaScriptはECMAScriptの実現である.ES 6の目標は、JavaScript言語が大型の複雑なアプリケーションを作成し、企業レベルの開発言語になるようにすることです.
    概念
    ES 6原生はPromiseの対象を提供しています.
    Promiseとは、相手が非同期操作のメッセージを伝えることです.これは、ある将来結果が分かるイベント(通常は非同期的な動作)を表し、このイベントは、統一したAPIを提供し、さらなる処理に供される.
    Promiseオブジェクトには以下の2つの特徴があります.
    (1)対象の状態は外部の影響を受けない.Promiseオブジェクトは非同期操作を表しています.Pending(進行中)、Resoloved(完了しました.Fulfilledとも言います.)とRejeced(失敗しました.)の3つの状態があります.非同期操作の結果のみ、現在の状態はどの状態かを決定できます.他の操作はこの状態を変えることができません.これもPromiseという名前の由来ですが、英語では「承諾」という意味で、他の手段は変えられないという意味です.
    (2)一旦状態が変わったら、二度と変わりません.いつでもこの結果が得られます.Promiseオブジェクトの状態が変わるのは、PendingからReolvedに変化することとPendingからRejectiedに変化することしかできません.この二つの状況が発生すれば、状態が固まり、これ以上変わることなく、ずっとこの結果を維持します.変更が発生したとしても、Promiseオブジェクトに対してコールバック関数を追加すると、すぐにこの結果が得られます.イベントとは全く違って、イベントの特徴は、それを見逃してしまったら、また傍聴しても結果が得られないということです.
    Promiseオブジェクトがあると、非同期動作の流れを同期させて表現でき、入れ子の回転関数が回避されます.また、Promiseオブジェクトは、非同期動作を制御することが容易になるように、統一されたインターフェースを提供する.
    Promiseにもいくつかの欠点があります.まず、Promiseをキャンセルすることができません.新築したらすぐ実行します.途中でキャンセルできません.次に、コールバック関数を設定しないと、Promise内部で投げられたエラーは外部に反応しません.第三に、Pendingの状態では、どの段階に進行しているかが分かりません.
    var promise = new Promise(function(resolve, reject) {
     if (/*        */){
     resolve(value);
     } else {
     reject(error);
     }
    });
    
    promise.then(function(value) {
     // success
    }, function(value) {
     // failure
    });
    
    Promiseコンストラクタはパラメータとして関数を受け入れ,この関数の二つのパラメータはそれぞれreolve法とreject法である.
    非同期操作が成功すれば、レシオ方式でPromiseオブジェクトの状態を「未完成」から「成功」に変えます.
    非同期操作が失敗したら、プロジェクト方法でPromiseオブジェクトの状態を「未完成」から「失敗」に変更します.
    基本的なアプリ
  • Promise.resove()
  • Promise.reject()
  • Promise.prototype.then()
  • Promise.prototype.ctch()
  • Promise.all()/すべての完了
    var p = Promise.all([p1,p2,p3]);
    
  • Promise.race()/競速は、一つで
  • です.
    階段を進める
    promisesの奇妙さは以前のreturnとthrowを与えてくれます.各Promiseはthen関数とcatch()を提供します.実際にはthen(null,...)関数です.
        somePromise().then(functoin(){
            // do something
        });
    
    
    私たちは3つのことができます.1.returnもう1つのpromise 2.returnの同期の値(またはundefined)3.throw同期異常throw new Eror('');1.パッケージ同期と非同期コード
    ```
    new Promise(function (resolve, reject) {
    resolve(someValue);
    });
    ```
      
    
    ```
    Promise.resolve(someValue);
    ```
    
    2.捕獲同期異常
     new Promise(function (resolve, reject) {
     throw new Error('   ,   bug  ');
     }).catch(function(err){
     console.log(err);
     });
    
    同期コードであれば、作成できます.
        Promise.reject(new Error("   "));
    
    
    3.複数の異常捕獲、より正確な捕獲
    somePromise.then(function() {
     return a.b.c.d();
    }).catch(TypeError, function(e) {
     //If a is defined, will end up here because
     //it is a type error to reference property of undefined
    }).catch(ReferenceError, function(e) {
     //Will end up here if a wasn't defined at all
    }).catch(function(e) {
     //Generic catch-the rest, error wasn't TypeError nor
     //ReferenceError
    });
    
    4.2つのPromiseの戻り値を取得する
    1. .then       
    2.          
    3. spread
    
    5.finally
              ,     catch   
    
    6.bind
    somethingAsync().bind({})
    .spread(function (aValue, bValue) {
     this.aValue = aValue;
     this.bValue = bValue;
     return somethingElseAsync(aValue, bValue);
    })
    .then(function (cValue) {
        return this.aValue + this.bValue + cValue;
    });
    
    あるいはあなたもこのようにすることができます.
    var scope = {};
    somethingAsync()
    .spread(function (aValue, bValue) {
     scope.aValue = aValue;
     scope.bValue = bValue;
     return somethingElseAsync(aValue, bValue);
    })
    .then(function (cValue) {
     return scope.aValue + scope.bValue + cValue;
    });
    
    しかし、これは非常に多くの違いがあります.
  • 資源の浪費とメモリ流出のリスクがあると先に宣言しなければなりません.
  • は、表現の文脈においては使用できません.
  • 効率が低い
  • .
    7.all.非常にダイナミックなサイズの均一なPromiseリストを処理するために使用されます.
    8.ジョン.複数の分離を扱うPromiseに最適です.
    ```
    var join = Promise.join;
    join(getPictures(), getComments(), getTweets(),
    function(pictures, comments, tweets) {
    console.log("in total: " + pictures.length + comments.length + tweets.length);
    });
    ```
    
    9.props.プロミセのmap集合を処理します.失敗が一つだけあります.すべての実行が終わります.
    ```
    Promise.props({
    pictures: getPictures(),
    comments: getComments(),
    tweets: getTweets()
    }).then(function(result) {
    console.log(result.tweets, result.pictures, result.comments);
    });
    ```
    
    10.any、some、race
    ```
    Promise.some([
    ping("ns1.example.com"),
    ping("ns2.example.com"),
    ping("ns3.example.com"),
    ping("ns4.example.com")
    ], 2).spread(function(first, second) {
    console.log(first, second);
    }).catch(AggregateError, function(err) {
    
    err.forEach(function(e){consolie.error(e.stack)};可能性があります.失敗のpromiseが多いため、Promsieは永遠にfulfilledできません.
    11.map(Function mapper[,Object options])
            ,   promise   ,
    
    Option:concurrencyそして発見
        map(..., {concurrency: 1});
    
    以下は合併数量を制限しないで、読書文書の情報です.
    var Promise = require("bluebird");
    var join = Promise.join;
    var fs = Promise.promisifyAll(require("fs"));
    var concurrency = parseFloat(process.argv[2] || "Infinity");
    
    var fileNames = ["file1.json", "file2.json"];
    Promise.map(fileNames, function(fileName) {
     return fs.readFileAsync(fileName)
     .then(JSON.parse)
     .catch(SyntaxError, function(e) {
     e.fileName = fileName;
     throw e;
     })
    }, {concurrency: concurrency}).then(function(parsedJSONs) {
     console.log(parsedJSONs);
    }).catch(SyntaxError, function(e) {
     console.log("Invalid JSON in file " + e.fileName + ": " + e.message);
    });
    
    結果
    $ sync && echo 3 > /proc/sys/vm/drop_caches
    $ node test.js 1
    reading files 35ms
    $ sync && echo 3 > /proc/sys/vm/drop_caches
    $ node test.js Infinity
    reading files: 9ms
    
    11.reduce(Function reducer[,dynamic initial Value])->Promise
    Promise.reduce(["file1.txt", "file2.txt", "file3.txt"], function(total, fileName) {
     return fs.readFileAsync(fileName, "utf8").then(function(contents) {
     return total + parseInt(contents, 10);
     });
    }, 0).then(function(total) {
     //Total is 30
    });
    
    12.Time
  • .delay(int ms)->Promise
  • .timeout(int ms[,String message]]]->Promise
  • Promiseの実現
  • q
  • ブルーバード
  • co
  • when
  • ASYNC
    async関数はPromise、Generator関数と同じで、コールバック関数の代わりに、非同期動作を解決する方法です.本質的にはGenerator関数のシンタックス飴です.async関数はES 6ではなく、ES 7に含まれています.
    参考文献(書き写してもいいという):
    阮一峰のES 6教程はpromisesについてどれぐらい理解しましたか?Bluebirdの公式文書
    流星の暴走
    リンク:http://www.jianshu.com/p/063f7e490e9a
    ソース:略書
    著作権は作者の所有に帰する.商業転載は作者に連絡して授権を獲得してください.商業転載ではないので、出典を明記してください.