0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

async/await使わないで同期実行的な書き方

0
Last updated at Posted at 2019-06-09

APIが提供されていないWebサービスのデータをプログラマティックに処理したいようなときにはpuppeteerをよく使うのですが、プロジェクトの規模が大きくなってくると、複雑な非同期処理のつじつま合わせに時間をとられるようになっていき、結局書いたコードを放棄するというようなサイクルを数年前から辿っていました

async/awaitを使うと同期実行っぽく書けるのですが、毎回毎回同じ文字を関数の前に書くのも芸がないし、かといってPromiseはインデントが深くなるし、コールバック地獄になるしで、うまい方法はないか考えていましたが、自分なりにしっくりくる方法が見つかったので、紹介します

It.js
const It=class {
  constructor(it){
    this.it=Promise.resolve(it);
    this.last=Promise.resolve();
  }

  does(fn, ...args){
    this.last=this.last.then(
      dummy => this.it.then(
        it => it[fn](...args)
      )
    );

    return this.last;
  }
}

クラス名とかファイル名は何でもいいんですが、上のコードでいうと

  1. コンストラクタで何らかのオブジェクト(コードではit)を受け取って、それをPromiseでくるんで持っておく
  2. doesという関数で1のPromiseからitを取り出して、itのメンバ関数を実行する(doesの第一引数で呼び出したいメンバ関数名を指定、第二引数以降はメンバ関数の引数)
  3. lastで最後に実行された3の結果を保持しておく(これもPromiseになる)

このクラスを拡張することで例えば、以下のようなことができます(puppeteerのラッパークラス)

Browser.js
const Browser=class extends It {
  constructor(){
    super(browser);
  }
}

const Page=class extends It {
  constructor(){
    super(
      new Browser()
        .does('newPage')
    );
  }
}

const page=new Page();
page.does('on', 'console',
  msg => console.log(msg.text())
);
page.does('goto', 'https://qiita.com/');
page.does('evaluate', ()=>{
  console.log('doing');

  return 'done'
}).then(console.log);
// doing
// done

does('on' ~ does('goto' ~ does('evaluate' ~ はそれぞれ前の処理が完了してから次の処理が実行されます(同期実行)
Itクラスの内部でPromiseを延々とつなげているだけなんですが、インデントしないで処理がかけます

戻り値で何か処理をしたい場合はdoes('evaluate' ~の部分のようにthen/catchで受け取ることもできます

あとasync/awaitの場合は、await中は関数の処理が止まるのですが、この書き方だとあくまでPromiseなので、後続の処理で別のPromiseがあれば、待たずに実行されます

毎回doesを書くのが嫌なら、必要に応じてdoesを隠蔽するfacade関数を各クラスに実装しておけばよいです

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?