LoginSignup
1
0

More than 3 years have passed since last update.

javascriptのPromiseをpythonで実装する方法

Posted at

Motive

selenium でスマホ版でブラウザを起動しようと思った時、

    sp_args = "--user-agent="
    sp_args_list = ["Mozilla/5.0 (iPhone; CPU iPhone OS 10_2 like Mac OS X)",
                    "AppleWebKit/602.3.12 (KHTML, like Gecko)",
                    "Version/10.0 Mobile/14C92 Safari/602.1"]
    sp_args += " ".join(sp_args_list)

と設定するだけでは一部のサイトではレスポンシブになっているため対応しない場合があります。

そのため、 width を450くらいにしてリロードをするとスマホ版の表示になるのですが、ブラウザ設定 → スマホ画面の大きさを設定 -> リロード の順に一つのプロセスが完了したことがcompleteになった状態で次のプロセスに移す実装ができないかと思ったわけです。

で、 javascriptの非同期処理で使われるPromiseと同等のものがpythonでできないかと考えたわけっす。

Preparetion

pip で探すと早速パッケージが見つかりました。ふつーに

pip install Promise

で良いです。

Model

参考にしたサンプルコードですが初めてのJavaScript 第3版 ――ES2015以降の最新ウェブ開発 14章 非同期プログラミングにあったロケット発射モデルを題材にしました。

元コードからブラウザに表示する編集等々でちょっと変えています。


<html>
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
        <script type="text/javascript" src="./sample.js"></script>
    </head>
    <body>
        <h3>apolonX</h3>
        <div class="box">
        </div>
    </body>

</html>

$(()=>{

    countdown(10)
    .then(()=>{
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                //大気圏突入
                resolve(insertBox("atmosphere..."));
            }, 2000);
        });
    })
    .then(()=>{
        //成功
        insertBox("success!!");
    });

});

//カウントダウン
function countdown(seconds){
    let dst = new Promise(
            (resolve, reject) => {
                for (let i=seconds;0 <=i;i--){
                    setTimeout(() => {
                        if(i>0){
                            insertBox(countSign(i));
                        } else {
                            resolve(insertBox(goSign()));
                        }
                    }, (seconds-i)*1000);
                }
            }
        );
    return dst
}


function insertBox(src){
    let p = $("<p>")
    p.text(src);
    $(".box").append(p);
}

function countSign(index){
    return index + "...";
}

function goSign(){
    return "GO!";
}

で約2秒ごとにブラウザにメッセージが表示されます。

count.gif

Method

from promise import Promise
import time

def main():
    countdown(10).then(go()).then(Promise.resolve(atmosphere())).then(success())

def countdown(seconds):
    def myfunc(resolve, reject):
        for i in reversed(range(0,seconds + 1)):
            if 0 < i:
                print( str(i) + "..." )
                time.sleep(2)
            else :
                resolve()
    return Promise(myfunc)

def go():
    time.sleep(1)
    print("GO")


def atmosphere():
    time.sleep(1)
    print("atmosphere")

def success():
    print("success!!")


if __name__ == '__main__':
    main()

countdown(10).then(go()).then(Promise.resolve(atmosphere())).then(success())
でチェイン化しています。

Aug 4 2019 1_22 PM - Edited.gif

Future

複数のAPIでデータ取得後に一括処理して文章生成するなどのケースであったら、全てのAPIのデータ取得後に一括処理する一貫性が保たれるので何かと良い。
簡易的なトランザクション処理ですかね。

Reference

promise
promise:github
初めてのJavaScript 第3版 ――ES2015以降の最新ウェブ開発 14章 非同期プログラミング
Python の Promise 実装とその活用方法について / How to implement Promise by Python and how to use it

1
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
1
0