私が理解しているPromise

4279 ワード

(私の话が多いのは分割线の后の部分を直接见ることができるのが嫌です…)以前高校の时自分でブログをいじって、ずっとJQueryでボタンの事件を书くだけで、フォームの提出さえ书いたことがなくて、后で误って先端を打って私达は昔JSの非同期のモードが本当にお父さんだと感じて、あなたが非同期の回调をはっきりさせる时、回调地狱(Callback Hell)太坑爸...どうして非同期坑爸だと思うの?次の例を見てみましょう.
//   setTimeout()      

function getName() {
  return "    ";
}

function greeting(name) {
  console.log("  ," + name);
}

//    0 1000    ,          0-1 
var randomTime = function () {
  return Math.random() * 1000;
};

var name = "";

//1    name        ,        
setTimeout(function () {
  name = getName();
}, randomTime());

greeting(name); //    name             ,  …

これは間違っています!これは間違っています!これは間違っています!
多くの初心者がこの間違いを犯したことがあるかもしれませんが、間違ったときはなぜ間違っているのか分かりません...原因を深く究明するとJSのメカニズムと関係があり、長々と議論しているのはここでは言いません(実は私にははっきり言えません...)
もう少し経験があれば、greeting(name)をコールバック関数に書くべきだということがわかります.そうすれば、データを得てからgreeting()関数を実行することを保証することができます.そこで...複数の要求があり、このような依存関係があるとき、恐ろしいコールバック地獄が現れます.回調地獄を解決する優雅な方法の一つは、伝説のpromiseを使うことだ.
promiseという概念については前後して1年ほど見ていましたが、周りにも知らない人が教えてくれて、自分でネット上の文章を見るしかありませんでしたが...卵用はありません...ネット上の文章は諸説あり、上がってくるとdeferの[1]、上がってくるとdeferを使っていたらPromiseの[2]、だから私は今でもどんな理解が正しいのか分からない...
PromiseやA+仕様についてはここで詳しくは述べませんが、それらの概念の東東については、私もまだ完全に理解していません.私がやりたいのは、私と同じシロにPromiseの最も基本的な使い方を理解させることです.
栗を挙げると...サードパーティが提供するAPIがあり、アクセスAPIはいくつかのユーザーデータ(アクセスごとに1ページを得ることができ、いくつかの制限によって1ページが3人のユーザーだけを返すと仮定する)と次のページのindexを得ることができる.最初のページを除いて、次のページのindexパラメータが必要です.(このAPIのデザインの不合理さはともかく…FacebookにはこのようなAPIがあります)http://example.com/user-->最初のページのユーザーデータへのアクセスhttp://example.com/user?next=xzmca-->2ページ目のユーザーデータ要求1ページ目にアクセスすると、次の結果が返されます.
{
"items" : [{
  "name" : "    ",
   "age" : 10
  }, 
{...}, {...}],
"nextPage" : "xzmca",
"lastPage" : null
}

あなたのアプリは一度に6つ以上のユーザーデータを表示する必要があります.前のAPIによると、一度に3つのデータしか入手できないので、2回のリクエストしか発行できません.そして、2回目のリクエストは1回目のリクエストに依存した結果、非同期の理由で最初のリクエストがいつ完了するか分かりません.私が最初にピットに入ったときは、プログラムに最初のリクエストを送信してから2秒待ってから2回目のリクエストを送信させました.教えてあげましょうか.
次に、便宜上、setTimeout()関数とbluebirdライブラリを使用して説明します.
//    0 3000    ,          0-3 
var randomTime = function () {
  return Math.random() * 3000;
};

//         promise resolve,     promise reject   
function req1() {
  return new Promise(function (resolve) {

    //  setTimeout()       ,data        
    setTimeout(function () {
      var data = {
        "items": [{
          "name": "    ",
          "age": 10
        }, {
          "name": "  ",
          "age": 100
        }, {
          "name": "  ",
          "age": 111
        }],
        "nextPage": "asdfa",
        "lastPage": null
      };

      resolve(data);
      console.log("  1  ");
    }, randomTime());
  })
}

function req2(dataFromReq1) {
  return new Promise(function (resolve) {

    setTimeout(function () {
      var data = {
        "items": [{
          "name": "    ",
          "age": 20
        }, {
          "name": "  ",
          "age": 233
        }, {
          "name": "  ",
          "age": 250
        }],
        "nextPage": "gwdfx",
        "lastPage": "asdfa"
      };
      console.log(dataFromReq1);
      var finalUserData = dataFromReq1.items.concat(data.items); //            
      resolve(finalUserData);
      console.log("  2  ");
    }, randomTime());
  })
}

//    promise        ~
req1().then(req2).then(function (data) {
  console.log(data);
});

Q:いつpromiseに戻る必要がありますか.A:需要ロジックがXXXの実行にOOOの結果に依存する必要がある場合、OOOはpromiseを返すべきです.
Q:どうしてreq 1は括弧で、req 2は括弧ではありませんか.A:これもよくわかりませんが、私の理解では、req1()はカッコをつけて実行してからpromiseに戻ります.カッコをつけないのは実行されていない関数です.req2はカッコをつけないのはthenのパラメータが1つの関数しかないので、カッコをつけて実行したら関数ではありません.
Q:最後のthenのfunction(data)dataはどこから来たのですか.A:req2の定義には、resolve(finalUserData)という言葉があります.Promise Chainでは、各thenの入参、すなわちfunction(data)のdataは、前のpromise resolveのときに渡されます.
  • https://github.com/alsotang/node-lessons/tree/master/lesson17 ↩
  • http://web.jobbole.com/82601/↩