You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript等待Tasker外部数据的循环实现问题求助

Tasker与WebView JS数据等待循环问题修复

问题背景

在Android设备的Tasker场景WebView中运行带JS的HTML页面,需要展示Google Places API结果。Tasker从Google拉取数据的流程正常,JS也能读取到数据,但构建等待Tasker完成检索的循环时出现两个问题:

  • 检测到控制变量匹配后,对应代码块重复执行多次
  • this.fillHtmlElements()函数完全没执行
  • 固定时长的setTimeout能运行,但无法适配网络波动情况

原尝试代码

loadContent(){
          const myInterval = setInterval(dataRetrieve, 500);
          let random = Math.random().toFixed(5); // 生成随机数作为控制变量
          setGlobal('CheckNumberIn', random); // 将控制变量设置到Tasker全局变量CheckNumberIn,Tasker完成加载后会把CheckNumberOut设为相同值
          performTask('loadingGoogle', '15', this.locationType, Data.distance); // 启动Tasker任务loadingGoogle获取数据,15是优先级,this.locationType是地点类型,Data.distance是搜索半径
          let counter = 0;
          function dataRetrieve() {
            let answer = global('CheckNumberOut'); // 获取Tasker全局变量CheckNumberOut的值
            if (answer == random) { // 检查控制变量是否相等,判断Tasker是否完成加载
                let retrievedData = global ('RetrievedData'); // 读取Tasker中存储的检索数据
                this.inputData = JSON.parse(this.retrievedData); // 解析JSON数据
                this.fillHtmlElements(); // 更新HTML元素
                clearInterval(myInterval);
            } else if (counter < 30) {
              counter++;
            } else {
              clearInterval(myInterval);
            }

          }
        }

问题根源

  1. this指向错误:dataRetrieve作为内部函数,在setInterval回调中执行时,this不再指向loadContent所属的对象,导致this.inputData和this.fillHtmlElements()无法正确访问,所以更新函数没执行。
  2. 重复执行未阻止:当控制变量匹配后,虽然调用了clearInterval,但已经进入执行队列的回调还会继续运行,导致代码块重复执行多次。

修复方案

修复后的代码

loadContent(){
  let isCompleted = false; // 标记是否已处理完成,防止重复执行
  const self = this; // 保存当前上下文的this引用
  const myInterval = setInterval(dataRetrieve, 500);
  let random = Math.random().toFixed(5);
  
  setGlobal('CheckNumberIn', random);
  performTask('loadingGoogle', '15', this.locationType, Data.distance);
  
  let counter = 0;
  
  function dataRetrieve() {
    if (isCompleted) return; // 已完成则直接返回,避免重复处理
    
    let answer = global('CheckNumberOut');
    if (answer == random) {
      isCompleted = true;
      clearInterval(myInterval); // 先清除定时器,阻止后续回调
      
      let retrievedData = global('RetrievedData');
      self.inputData = JSON.parse(retrievedData); // 使用self访问原上下文的属性
      self.fillHtmlElements(); // 执行HTML更新函数
    } else if (counter < 30) {
      counter++;
    } else {
      clearInterval(myInterval);
      // 这里可以添加超时提示逻辑,比如给用户显示加载失败
    }
  }
}

简化版(箭头函数)

箭头函数会继承外层作用域的this,可以省去保存self的步骤:

loadContent(){
  let isCompleted = false;
  let random = Math.random().toFixed(5);
  let counter = 0;
  
  setGlobal('CheckNumberIn', random);
  performTask('loadingGoogle', '15', this.locationType, Data.distance);
  
  const myInterval = setInterval(() => {
    if (isCompleted) return;
    
    let answer = global('CheckNumberOut');
    if (answer == random) {
      isCompleted = true;
      clearInterval(myInterval);
      
      let retrievedData = global('RetrievedData');
      this.inputData = JSON.parse(retrievedData);
      this.fillHtmlElements();
    } else if (counter < 30) {
      counter++;
    } else {
      clearInterval(myInterval);
    }
  }, 500);
}

进阶优化(Promise封装)

用Promise封装等待逻辑,让代码更清晰易读:

// 封装等待Tasker数据的函数
function waitForTaskerData(checkValue) {
  return new Promise((resolve, reject) => {
    let counter = 30;
    const interval = setInterval(() => {
      const answer = global('CheckNumberOut');
      if (answer === checkValue) {
        clearInterval(interval);
        resolve(global('RetrievedData'));
      } else if (--counter <= 0) {
        clearInterval(interval);
        reject(new Error('数据加载超时'));
      }
    }, 500);
  });
}

// 异步方式调用
async loadContent() {
  const random = Math.random().toFixed(5);
  setGlobal('CheckNumberIn', random);
  performTask('loadingGoogle', '15', this.locationType, Data.distance);
  
  try {
    const retrievedData = await waitForTaskerData(random);
    this.inputData = JSON.parse(retrievedData);
    this.fillHtmlElements();
  } catch (error) {
    console.error(error);
    // 这里处理超时或加载失败的情况,比如给用户提示
  }
}

内容的提问来源于stack exchange,提问作者Philipp Mayer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 06:45:53