如何在JavaScript中插入延迟?AppleScript运行JS网页抓取遇阻
解决AppleScript中JavaScript网页抓取的同步执行问题
问题描述
在AppleScript中运行JavaScript进行网页抓取时,遇到以下问题:
- 原代码里
wait()函数未定义,执行报错 - 尝试使用
await new Promise(...)时提示“new”意外 - 需要保证
inputPunch函数完全执行完毕后,才进入下一次循环迭代
原代码如下:
function inputPunch(date_string) { // do task 1 wait(3000); // do task 2 wait(3000); // do task 3 wait(3000); // do final task } // get start date value var date_obj = new Date(start_date_value); date_obj.setDate(date_obj.getDate() + 2); for(let i = 0; i < 12; i++) { let cur_date_string = date_obj.toDateString(); let cur_date_array = cur_date_string.split(" "); cur_date_array[2] = cur_date_array[2].replace(/^0+(\d)|(\d)0+$/gm, '$1$2'); let cur_formatted_date_string = cur_date_array[1].concat(" ", cur_date_array[2], ",", cur_date_array[3]); console.log(cur_formatted_date_string); // call inputPunch at each iteration of the for loop inputPunch(cur_formatted_date_string); date_obj.setDate(date_obj.getDate() + 1); }
重构方案
由于AppleScript的JS运行环境对async/await支持有限,推荐两种可靠的实现方式:
方案一:回调函数+递归(兼容性强)
这种方式不依赖Promise,适配大多数AppleScript JS环境:
- 封装回调式等待函数
function wait(ms, callback) { setTimeout(callback, ms); }
- 重构
inputPunch为回调驱动的异步函数
把每个任务拆分为异步步骤,所有任务完成后调用回调通知外部:
function inputPunch(date_string, doneCallback) { // 执行Task 1 // ... 这里替换为你的UI操作代码 ... wait(3000, function() { // 执行Task 2 // ... 这里替换为你的UI操作代码 ... wait(3000, function() { // 执行Task 3 // ... 这里替换为你的UI操作代码 ... wait(3000, function() { // 执行Final Task // ... 这里替换为你的UI操作代码 ... // 所有任务完成,触发下一步 doneCallback(); }); }); }); }
- 用递归替代for循环
确保每次迭代都在上一次inputPunch执行完成后才启动:
// 初始化日期和迭代计数 var date_obj = new Date(start_date_value); date_obj.setDate(date_obj.getDate() + 2); var iterationCount = 0; const totalIterations = 12; // 递归执行迭代的函数 function runNextIteration() { if (iterationCount >= totalIterations) return; // 格式化当前日期 let cur_date_string = date_obj.toDateString(); let cur_date_array = cur_date_string.split(" "); cur_date_array[2] = cur_date_array[2].replace(/^0+(\d)|(\d)0+$/gm, '$1$2'); let cur_formatted_date_string = cur_date_array[1].concat(" ", cur_date_array[2], ",", cur_date_array[3]); console.log(cur_formatted_date_string); // 调用inputPunch,传入完成回调 inputPunch(cur_formatted_date_string, function() { date_obj.setDate(date_obj.getDate() + 1); iterationCount++; // 启动下一次迭代 runNextIteration(); }); } // 启动整个流程 runNextIteration();
方案二:Async/Await(环境支持时使用)
如果你的AppleScript JS环境支持Promise和async/await,可以用更简洁的写法:
- 封装Promise版等待函数
function wait(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }
- 把
inputPunch改为async函数
async function inputPunch(date_string) { // Task 1 // ... 你的UI操作代码 ... await wait(3000); // Task 2 // ... 你的UI操作代码 ... await wait(3000); // Task 3 // ... 你的UI操作代码 ... await wait(3000); // Final Task // ... 你的UI操作代码 ... }
- 用自执行异步函数处理循环
(async function() { var date_obj = new Date(start_date_value); date_obj.setDate(date_obj.getDate() + 2); for(let i = 0; i < 12; i++) { let cur_date_string = date_obj.toDateString(); let cur_date_array = cur_date_string.split(" "); cur_date_array[2] = cur_date_array[2].replace(/^0+(\d)|(\d)0+$/gm, '$1$2'); let cur_formatted_date_string = cur_date_array[1].concat(" ", cur_date_array[2], ",", cur_date_array[3]); console.log(cur_formatted_date_string); // 等待inputPunch执行完成再进入下一次循环 await inputPunch(cur_formatted_date_string); date_obj.setDate(date_obj.getDate() + 1); } })();
如果方案二报错“new”意外,说明环境不支持Promise,直接用方案一即可。
内容的提问来源于stack exchange,提问作者Dyskord
相关产品推荐
相关产品推荐

