4

this SO questionに基づいて、Wicket が後続の AJAX リクエストをキューに入れることを理解しました。現在、私のページはいくつかの AJAX リクエストでいっぱいです。時間のかかる操作を生成するリクエストをもう 1 つ追加したいと思います。

public void populateItem(final Item item) {
  final MyObject object = (MyObject) item.getModelObject();
  // ... a couple of fields
  Label statusLabel = new Label("status", new AbstractReadOnlyModel() {
    @Override
    public Object getObject() {
      return someService.doSomeLengthyOperation();
    }
  });
  statusLabel.add(new AjaxSelfUpdatingTimerBehavior(Duration.seconds(5)));
  item.add(statusLabel)
}

この Ajax リクエストが発生すると、実行が完了するまでに最大 1 分かかる場合があります。ここでの問題は、私が持っているsomeService.doSomeLengthyOperation()実行されることです。つまり、キューに入れられます。前述したように、Wicket は後続の AJAX リクエストをキューに入れます。n times the number of rowsn times two-minutes

何が起こるかというとnumber-of-rows * minutes-it-take-to-finish-the-operation、ページをロードしたり、AJAX のようなものを必要とする他のことをしたりするのに時間がかかるということです。

new AjaxButton("ajax-button"){
  @Override
  protected void onSubmit(AjaxRequestTarget target, Form form) {
    //.. this won't be executed until all the statusLabels have finished invoking getObject()
  }
}

自分のサービスを公開する Web サービスを作成したり、独自の AJAX 呼び出しを作成したりする必要はありません。私のオプションは何ですか?(Wicket 1.5 / Pax-Wicket を使用)

4

2 に答える 2

3

最も簡単な方法は、最初の Ajax リクエストを (結果なしで) 高速に返し、ターゲット コンポーネントにAjaxSelfUpdatingTimerBehaviorを追加することです。結果がある場合、この動作は一定の間隔 (10 秒ごとなど) をチェックします。結果がある場合は、コンポーネントを更新し、それ自体を削除する必要があります。

このようにして、Ajax 呼び出しをブロックすることなく、別のタスクで操作を実行できます。

少し詳しく説明するために、説明したように 5 つの Ajax 呼び出しを発行する実行可能なクイックスタートを作成し、それぞれが 10 秒から 1 分の間のランダムな時間を実行します。同時に、カウンター付きのレスポンシブ AjaxLink があります。

主なアイデアは、実際の Ajax 呼び出しを遅いメソッドの呼び出しから分離することです。

add(new ListView<DataHolder>("list", list) {

    @Override
    protected void populateItem(ListItem<DataHolder> item) {
        DataHolder dh = item.getModelObject();
        item.add(new Label("itemNumber", new PropertyModel<Integer>(dh, "number")));
        Label result = new Label("itemResult", new PropertyModel<String>(dh, "result"));
        result.setOutputMarkupId(true);
        result.add(new AjaxSelfUpdatingTimerBehavior(Duration.seconds(2)));
        item.add(result);
        Thread thread = new Thread(new Processor(item.getModelObject()));
        thread.start();
    }
});

ご覧のとおり、ラベル モデルは直接呼び出されdoSomeLengthyOperation()なくなりました。代わりに、面倒な作業を行う新しいスレッドが生成されます。Processor クラスは Runnable インターフェースを実装し、 run-method を使用して作業を行います(あなたの場合、デモではしばらく待つだけです)。

PropertyModel の getter は、このスタントをカプセル化し、ブロックを防ぐために常に高速に戻りながら透明にします。

public String getResult() {
    String retValue;
    if (!processed) {
        retValue = String.format("Still busy after %d requests", counter++);
    } else {
        retValue = result;
    }
    return retValue;
}

処理されたメンバーは単なるフラグであり、プロセッサがいつ待機を完了したかを示すために使用します (ehr working)。

おそらく同時に 5 つ以上のスレッドを発行することになるため、何らかのスレッドプールを使用することをお勧めしますが、それはこの小さなデモの範囲を超えています。


免責事項: これは製品コードではありません。デモ用です。それはあなたのリソースに優しくないし、リソースの不足を適切に処理することもできません。ユーザーのリロードがヒットしたとき、または何か他のことが起こったときは機能しません。

于 2013-03-11T12:45:49.387 に答える
0

WicketStuff Async Task が役立つかどうかは完全にはわかりませんが、試してみてください。

https://github.com/wicketstuff/core/wiki/Async-tasks

Async Tasks プロジェクトにある短いデモを次に示します。

public class DemoPage extends WebPage implements IRunnableFactory {

public DemoPage() {

    Form<?> form = new Form<Void>("form");
    AbstractTaskContainer taskContainer = DefaultTaskManager.getInstance()
        .makeContainer(1000L, TimeUnit.MINUTES);
    ProgressButton progressButton = new ProgressButton("button", form, 
        Model.of(taskContainer), this, Duration.milliseconds(500L));
    ProgressBar progressBar = new ProgressBar("bar", progressButton);

    add(form);
    form.add(progressButton);
    form.add(progressBar);
}

@Override
public Runnable getRunnable() {
    return new IProgressObservableRunnable() {
        // Runnable implementation.
    };
}
于 2015-12-17T12:45:36.000 に答える