浏览代码

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:
 The ``spec`` fields of ``pin_wait`` commands:
 
 
-* names
+* names: list,
+* timeout: int,
 
 
 
 
 popup
 popup

+ 6 - 3
pywebio/pin.py

@@ -238,12 +238,15 @@ class Pin_:
 pin = 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,
     """``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.
     the function returns with the name and value of the changed widget.
 
 
     :param str names: List of names of pin 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.
     :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)):
     if len(names) == 1 and isinstance(names[0], (list, tuple)):
         names = names[0]
         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()
     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') {
         } else if (msg.command === 'pin_update') {
             PinUpdate(msg.spec.name, msg.spec.attributes);
             PinUpdate(msg.spec.name, msg.spec.attributes);
         } else if (msg.command === 'pin_wait') {
         } 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) {
             Promise.resolve(p).then(function (value) {
                 state.CurrentSession.send_message({event: "js_yield", task_id: msg.task_id, data: value});
                 state.CurrentSession.send_message({event: "js_yield", task_id: msg.task_id, data: value});
             }).catch((error) => {
             }).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->[]
 let onchange_callbacks: { [name: string]: ((val: any) => void)[] } = {}; // name->[]
 
 
-export function WaitChange(names: string[]) {
+export function WaitChange(names: string[], timeout: number) {
     let promises = [];
     let promises = [];
     for (let name of names) {
     for (let name of names) {
         if (!(name in onchange_callbacks))
         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);
     return Promise.race(promises);
 }
 }