浏览代码

feat: `pin_wait_change()` support `timeout` parameter

wangweimin 3 年之前
父节点
当前提交
7512fa10f0
共有 4 个文件被更改,包括 17 次插入6 次删除
  1. 2 1
      docs/spec.rst
  2. 6 3
      pywebio/pin.py
  3. 1 1
      webiojs/src/handlers/pin.ts
  4. 8 1
      webiojs/src/models/pin.ts

+ 2 - 1
docs/spec.rst

@@ -267,7 +267,8 @@ pin_wait
 
 The ``spec`` fields of ``pin_wait`` commands:
 
-* names
+* names: list,
+* timeout: int,
 
 
 popup

+ 6 - 3
pywebio/pin.py

@@ -238,12 +238,15 @@ class Pin_:
 pin = Pin_()
 
 
-def pin_wait_change(*names):
+def pin_wait_change(*names, timeout=None):
     """``pin_wait_change()`` listens to a list of pin widgets, when the value of any widgets changes,
     the function returns with the name and value of the changed widget.
 
     :param str names: List of names of pin widget
-    :return dict: ``{"name": name of the changed widget, "value": current value of the changed widget }``
+    :param int/None timeout: If ``timeout`` is a positive number, ``pin_wait_change()`` blocks at most ``timeout`` seconds
+        and returns ``None`` if no changes to the widgets within that time. Set to ``None`` (the default) to disable timeout.
+    :return dict/None: ``{"name": name of the changed widget, "value": current value of the changed widget }`` ,
+        when a timeout occurs, return ``None``.
 
     :demo_host:`Here </markdown_previewer>` is an demo of using `pin_wait_change()` to make a markdown previewer.
 
@@ -257,7 +260,7 @@ def pin_wait_change(*names):
     if len(names) == 1 and isinstance(names[0], (list, tuple)):
         names = names[0]
 
-    send_msg('pin_wait', spec=dict(names=names))
+    send_msg('pin_wait', spec=dict(names=names, timeout=timeout))
 
     return get_client_val()
 

+ 1 - 1
webiojs/src/handlers/pin.ts

@@ -20,7 +20,7 @@ export class PinHandler implements CommandHandler {
         } else if (msg.command === 'pin_update') {
             PinUpdate(msg.spec.name, msg.spec.attributes);
         } else if (msg.command === 'pin_wait') {
-            let p = WaitChange(msg.spec.names);
+            let p = WaitChange(msg.spec.names, msg.spec.timeout);
             Promise.resolve(p).then(function (value) {
                 state.CurrentSession.send_message({event: "js_yield", task_id: msg.task_id, data: value});
             }).catch((error) => {

+ 8 - 1
webiojs/src/models/pin.ts

@@ -27,7 +27,7 @@ export function PinUpdate(name: string, attributes: { [k: string]: any }) {
 
 let onchange_callbacks: { [name: string]: ((val: any) => void)[] } = {}; // name->[]
 
-export function WaitChange(names: string[]) {
+export function WaitChange(names: string[], timeout: number) {
     let promises = [];
     for (let name of names) {
         if (!(name in onchange_callbacks))
@@ -39,6 +39,13 @@ export function WaitChange(names: string[]) {
             });
         }));
     }
+    if (timeout) {
+        promises.push(new Promise(resolve => {
+            setTimeout(() => {
+                resolve(null);
+            }, timeout * 1000);
+        }));
+    }
     return Promise.race(promises);
 }