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秒ごとにブラウザにメッセージが表示されます。
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())
でチェイン化しています。
Future
複数のAPIでデータ取得後に一括処理して文章生成するなどのケースであったら、全てのAPIのデータ取得後に一括処理する一貫性が保たれるので何かと良い。
簡易的なトランザクション処理ですかね。
Reference
promise
promise:github
初めてのJavaScript 第3版 ――ES2015以降の最新ウェブ開発 14章 非同期プログラミング
Python の Promise 実装とその活用方法について / How to implement Promise by Python and how to use it