非同期——CallbackからPromiseまでRxjsへ

4326 ワード

ブログのアドレス:http://www.liushihua.org/2017/08/31/callback-promise-rxjs.html この文章はJavaScript demoがブログで直接実行できます.
异歩プログラミングの変迁の歴史、本文はただ本人の异歩のプログラミングの知识に対する整理として、同时にみんなに各种の方法の违う使い方を展示します.
Callback
大昔の時代に、人々は非同期プログラミングを実現するために、通常はcalbackの形式を採用して、1つのコールバック関数を定義して、非同期要求が必要なところで、コールバック関数を登録して、異常要求が戻ったら、データをコールバック関数に伝えて、非同期要求の結果を処理します.
以下の通りです
const callback = () => {
console.log('I am a callback');
}

console.log('Hello');
setTimeout(callback, 1000);
console.log('world);

0;
このような方式は初めて簡単明瞭に見えるが、複雑さの試練に耐えられず、複数の非同期の入れ子であれば、すぐに難しくなり、コードを継続することができる.
const log = console.log;
setTimeout(() => {
  log('     ');
  setTimeout(() => {
    log('     ');
    setTimeout(() => {
      log('     ');
      setTimeout(() => {
        log('     ');
      }, 1000)
    }, 1000)
  }, 1000)
}, 1000);
log('hello')

0;
このようなコードは読むのに役立ちません.メンテナンスにも役立ちません.次はPromiseです.とても重要なタイプです.
Promise
Promiseは約束を表しています.彼は一定の時間内に彼の事件を完成させたり、間違ったことを投げ出したりすることができます.つまり、生成したばかりの時は彼の状態が不確定で、一定の時間後には彼の状態が確定します.同時に二つの状況しかなく、一つは順調に完成します.一つは間違いの異常です.コードを作成する過程では、この二つの状態をモニターするだけでその結果を処理できます.以下はPromiseを使ったシミュレーション時間の非同期操作です.
const reqPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    console.log('Request  ');
    resolve({data: 1})
  },1000)
})

reqPromise.then(x => console.log(x));

0;
もっと面倒に見えますか?ちょっと複雑さを増してみます.以下はPromiseネストの場合です.
const getPromise = x => new Promise((resolve, reject) => {
  setTimeout(() => {
    console.log(x);
    resolve({data: 1})
  },1000)
});

getPromise('   ').then(x => getPromise('   '))
          .then(x => getPromise('   '))
          .then(x => getPromise('   '))
          .then(x => getPromise('   '))
          
0;
上の段はPromiseで書いたのですが、Callbackを直接使って書いたのと比べて、かなりはっきりしていますよね.フラットなチェーンを使って、マルチレベルの入れ子構造を代用して、コードの維持にもかなりはっきりしています.
でもこれで満足ですか?
No、チェーン呼び出しにはまだいくつかの表記上の問題があります.上記の例は全部非同期コードです.同期コードを書く必要があれば、Promiseの外で書く必要があります.非同期コードはPromiseのresoveの中で書くので、コードの読み取り可能性が失われます.すべてのコードを同期と見なしてもいいですか?これでコードのスタイルが統一されるのではないですか?
最新のes 2017バージョンにはasync/swaitという表記がありますが、これは新しい機能ではなく、Promiseの文法飴と見なされます.
上のPromiseコードを変更したらどうですか?
const getPromise = x => new Promise((resolve, reject) => {
  setTimeout(() => {
    console.log(x);
    resolve({data: 1})
  },1000)
});

const run = async () => {
  await getPromise('   ').then(x => console.log('      Resolve'))
  console.log('            ');
  await getPromise('   ').then(x => console.log('      Resolve'))
  console.log('            ');
  await getPromise('   ').then(x => console.log('      Resolve'))
  console.log('            ');
};

//   
run();

0;
このようなコードはいかがですか?
私たちは最初からCallbackのような一山がPromiseの線に圧縮されました.そしてこの線をasync/awaitで四角い紙に折りました.大きな進歩を感じたことはありませんか?
焦らないでください.続けて考えてみます.同期と非同期のコードをすべて非同期として扱うことができますか?これはコードを正しく書いてもいいですか?
したがって、応答式プログラミングは時に発生します.
Rxjs
Rxjsは応答式プログラミングとイコールではなく、RP(Reactive Proggramming)の一つのクラスだけで実現されていますが、ほとんどの主流言語で実現されていますので、すべてのrxはrpの中の中堅と言えるでしょう.
rxjsを深く紹介する前に、先にrxjsコードを使って上記の例を実現します.
const { Observable: ob} = require('rxjs');

const getPromise = x => new Promise((resolve, reject) => {
  setTimeout(() => {
    console.log(x);
    resolve({data: 1})
  },1000)
});

ob.from(getPromise('   '))
  .map(x => console.log('            '))
  .flatMap(x => getPromise('   '))
  .map(x => console.log('            '))
  .flatMap(x => getPromise('   '))
  .map(x => console.log('            '))
  .flatMap(x => getPromise('   '))
  .map(x => console.log('            '))
  .flatMap(x => getPromise('   '))
  .map(x => console.log('            '))
  .subscribe()

0;
今は一重ねの紙からもう一本の線に戻りました.いや、正確にはパイプになりました.同期動作であろうと、非同期動作であろうと、このパイプの中で宣言されています.スタート信号はパイプの中のすべての同期または非同期操作を経て最後の出力に到達します.つまり、購読します.
ちょっとお邪魔します
非同期プログラミングの书き方の変更は、符号化効率の変化だけでなく、コードスタイルのアップグレードだけではありません.これはプログラミングモードの変更です.最も主要なのは思考方式の転換を促進することです.応答式プログラミングは、さまざまな角度から問題の解を考えることができます.後〇〇時代では、これは非常に貴重です.