[ 新規に投稿する ]

非同期マクロ同時の順番を制御しやすくする機能No.10696
こみやんま さん 25/04/28 01:15 [ コメントを投稿する ]
  非同期マクロ同時の順番を制御しやすくする機能を提案します。

■ 非同期のスクリプトは主に2系統

@ 常時実行している。
 1時間でも2時間でも、該当のファイルがオープンしている限り、
 裏でずっと動いているもの

A 数秒など、短時間だが時間がかかるので非同期にまわしているか、
 あるいは非同期要素があるので、非同期になっている。
 ・テキスト数十万行などが対象で、完了に数秒かかる
 ・ネットワークAPIを利用しているため、返答に0.5〜3秒ほどかかる

 ネットワークサービスはほとんどが rest api ですが、
 原則 jsmode の fetch を使ってアクセスするでしょうから、
  (同期でやったら明らかに秀丸が硬直するのでw)
 Promiseで書こうが、await で書こうが必然的に非同期になるでしょう。


問題はAの非同期のマクロの(あくまでも概念的な)終了をいかにして待つのがスマートなのか?
ということです。

■ awaitjs は筋が悪い

すでに秀丸に実装されている「awaitjs」は、
「同期」待機(「マクロ実行中」というステータスでの待機)となるため、
正直「仕様がすごく悪い」といえます。
(以前もこのことを強く講義しましたw)

同期待機であるため、非常にデッドロックしやすく、かつ、
全ての秀丸を巻き込みやすいです。

同期待機してるものだから、待機の間、「新たなマクロ実行」も「postExec」も効かなくなり、
javascriptの処理に「ほんの僅かな綻び」があるだけで、
あっけなくデッドロックし、詰みやすい

■ 非同期のものは、非同期として待機し、条件を満たしたら呼び出してもらうのが良い形

そうではなく、JavaScriptらしく、
あくまでも非同期の中で非同期として待機します。

以下の形を提案します。


「待機」をしていても、
・「新たなマクロ実行」も
・「他の非同期処理実行」も、
両方の邪魔をしない形です。


// マクロA
jsmode "JScript\\" + "func1_" + currentmacrofilename;

js {

    debuginfo(2);
    
    // 非同期であるものの「終了の概念」があるマクロなのであれば、その気付き情報を先頭(付近で)クリアする。
    hidemaru.setJsCompleteNotify("HmTestMacro1", "");
    
    function func1() {
        console.log("func1");
        // そして、その処理が完了したら(あくまでも、その作者にとっての概念的な終了だけど)、その情報を気付きとして登録する。
        hidemaru.setJsCompleteNotify("HmTestMacro1", "end");
    }

    hidemaru.setTimeout(func1, 3000);
 
}


// マクロB

// ファイル2がマクロAに続けて execmacro などされてるとする。
// マクロAの(概念的な)終了を待って、直後に(実質的な)実行を行いたいとする。
jsmode "JScript\\" + "func2_" + currentmacrofilename;

js {

    debuginfo(2);

    function mainAsync() {
        console.log("待ってたよ");
    }
    
    // マクロAの(非同期の)、とある気付き情報を、非同期のまま(他の邪魔をせず)待機する。
    // ただし、最大で10秒(10000ミリ秒)まで。
    hidemaru.waitJsCompleteNotify("HmTestMacro1", "end", mainAsync, {timeout:10000});
}





■ 実装したとしたらの挙動

上で出現している、2つの未実装の
@ hidemaru.setJsCompleteNotify
A hidemaru.waitJsCompleteNotify
の2つの関数は、
現段階でも以下のように仮組みすれば、どういった挙動になるのか確認できます。

// Aのマクロの先頭にこれを貼り付け
hidemaru.setJsCompleteNotify = function(label, notifyName) {
    setstaticvariable(label, notifyName, 2);
}

// Bのマクロの先頭にこれを貼り付け
hidemaru.waitJsCompleteNotify = function(label, notifyName, onEndCallbackFunction, option) {
        
    var tickHandler = null;
    function tick() {
        var currentStatus = getstaticvariable(label, 2);
        
        if (currentStatus == notifyName) {
            hidemaru.clearTimeout(tickHandler);
            if (typeof(onEndCallbackFunction) == "function") {
                onEndCallbackFunction();
            }
        }
        else {
            tickHandler = hidemaru.setTimeout(tick, 100);
        }
    }
    
    tickHandler = hidemaru.setTimeout(tick, 0);
    
    // タイムアウトしてる
    if (option && option.timeout) {
        hidemaru.setTimeout( function() { hidemaru.clearTimeout(tickHandler); }, option.timeout );
    }
}
[ ]
RE:10696 非同期マクロ同時の順番を制御しやすくする機能No.10698
秀丸担当 さん 25/04/28 12:18 [ コメントを投稿する ]
  秀丸エディタは独自のリッチなアプリケーション実行プラットフォームを目指しているわけではなく、awaitjsは、従来マクロの親和性が高く、普通は全体で1つのマクロ実行でよくて、これをベストプラクティスとしてもらっていいです。
簡単に記述できるのが一番いいです。
ですがそれでは不満もあるので、必要であればリッチな方法でもできる、ということでお願いします。
非同期の順次実行は、Aが実行中でなければ即実行、Aが実行中であればタイマー等で定期的に調べて終わったら実行、が簡単でいいと思います。
ご意見参考にさせていただきます。
[ ]
RE:10698 非同期マクロ同時の順番を制御しやすくする機能No.10699
こみやんま さん 25/04/28 16:53 [ コメントを投稿する ]
  > awaitjsは、従来マクロの親和性が高く

だとするならば、

https://help.maruo.co.jp/hidemac/html/110_MacroStatement_awaitjs.html

のサンプルだと、
```
何か非同期で目的の処理が完了するまでawaitjsで待機するもの
```

みたいに思えるので、

(※この考え方だと非同期処理の中で「同期関数が必要」だと実行できないので「詰む」と思ってしまう)


むしろ、まさに
```
同期関数が必要となるタイミングでnotifyAwaitし、順序立てた記述ができますよ
```

ぐらいで、サンプルを増やすと、見方が変わるかとは思います。

まさに
```
同期関数が必要になるタイミングで非同期から抜け出し
 ⇒ 同期処理
  ⇒ また非同期になっても、同期が必要になる
   ⇒ 同期処理

こういったものを逐次実行みたいなのをしやすい、
みたいなことを記述すればよいかと。


jsmode "JScript\\" + currentmacrofilename;

js {
var text = "";
    function asyncFunc1() {
        try {
            text = "bbbb";

            // この後begingroupundo() など、同期関数の処理が必要になる

        } catch(e) {
        } finally {
            // どのような状況でも必ず抜ける必要があるので発行は必要
            hidemaru.notifyAwait("asyncFunc1");
        }
    }
    
    // 何か重い処理して返ってくるんだ
    hidemaru.setTimeout(asyncFunc1, 1000);
}

awaitjs("asyncFunc1");

js {
    begingroupundo();
    insert(text);
    endgroupundo();
    
    function asyncFunc2() {
        try {
            renderpanecommand({
                target: "EndNotify",
                place: "bottom",
                size: 70,
                url: 'data: text/plane, "OK"'
            });bbbb
        
            // この後、message や endmacro 関数など、同期処理が必要
            
        } catch(e) {
        } finally {
            // どのような状況でも必ず抜ける必要があるので発行は必要
            hidemaru.notifyAwait("asyncFunc2");
        }
    }
    // 何かネットワークで処理して返ってくるんだ
    hidemaru.setTimeout(asyncFunc2, 100);
    
}

message "終わりました";
endmacro "complete";
[ ]
RE:10698 非同期マクロ同時の順番を制御しやすくする機能No.10700
こみやんま さん 25/04/28 17:20 [ コメントを投稿する ]
  話が全然関係ないところに行ってしましますが、
ちょっと「data:text/plain」が出てきたので...

ヘルプのレンダリングペインとか
(一応ブラウザ枠でも使えるけど普通はブラウザ枠には使わないと思いますが)

URLは 「http:」 「file:」 「javascript:」 だけではなく、「data:」も使えるいうことを書いたほうがよいかも。

data はレンダリングペインと相性が良いと思います。

変にurlencodeしなくてよいですし、受け口のhtmlへとjsで送信するより、簡単になることが多いのでは...

> renderpanecommand({
>     target: "EndNotify",
>     place: "bottom",
>     size: 70,
>     url: 'data: text/plane, "OK"'
> });bbbb

https://xn--pckzexbx21r8q9b.net/?page=nobu_tool_hm_webview2_renderpane_data_url
[ ]
RE:10699 非同期マクロ同時の順番を制御しやすくする機能No.10701
こみやんま さん 25/04/28 17:34 [ コメントを投稿する ]
  あ、私が大きく勘違いしてますねw

非同期中に同期関数がそのまま非同期関数内で呼べることに最大のメリットがあるのか。

[ ]
RE:10701 非同期マクロ同時の順番を制御しやすくする機能No.10702
こみやんま さん 25/04/28 17:41 [ コメントを投稿する ]
  ヘルプのサンプル内の、function の1つでも良いので、
同期関数を記述した方がよいかと。

// ------------------------------------

debuginfo 2;
debuginfo "\n開始\n";
js{
  hidemaru.setTimeout(
    function(){
      「この辺に同期関数を記述 (たとえば、menu 関数でもなんでも例として記述)」 // ★ このように非同期中に同期関数が記述できる。
      console.log("timeout");
      hidemaru.notifyAwait("KEYWORD");//awaitjsの待機を抜ける
    }
    , 1000 );
}
awaitjs "KEYWORD";
debuginfo "\n終了\n";
endmacro;

// ------------------------------------
みたいな。
[ ]
RE:10702 非同期マクロ同時の順番を制御しやすくする機能No.10703
秀丸担当 さん 25/04/30 09:47 [ コメントを投稿する ]
  awaitjsのサンプルは、確かに同期関数の例があるといいと思います。
非同期の例としては典型的にwebへのリクエストとレスポンス待ちがあったらいいかもしれないです。
ご意見参考にさせていただきます。
[ ]

[ 新規に投稿する ]