JavaScript中的定时器setInterval是计时到才会开始执行,有没有办法再定义的时候就先调用一遍,然后再定时执行呢?
有,只要定义一个返回“定时执行函数”(如“waitUploadThenSave”)的“执行过程”, 将“定时执行函数”保存并调用一次,并且执行过程中返回该“定时执行函数”,将该“执行过程”的主体作为定时器要定时执行的function即可。可参考以下代码理解:
var count = 0;
var bNoNeedTimerRun = false;
var id = setInterval(
(function () {
var waitUploadThenSave = function () {
//等待上传执行完成后保存数据:
if (pThis.fileList.every(x => x.status == 'success')) {
clearInterval(id);
if (bNoNeedTimerRun) {
//初始运行时就检测到都已上传完成,则定时运行中无须做任何事情,清除定时器即可
return;
}
if (!id) {
//初始运行时未完成id赋值,此时就检测到都已上传完成,则无需再定时检测运行
bNoNeedTimerRun = true;
}
setTimeout(() => pThis.saveTaskInfo(), 20); //wait for running on-success callback for upload
return;
} else {
if (++count > 600) {
clearInterval(id);
pThis.$message({
message: `上传资料${pThis.task.TaskText ? "“" + pThis.task.TaskText + "”" : ""}执行超时,未执行保存!`,
type: 'error'
});
}
}
}
waitUploadThenSave();
return waitUploadThenSave;
})()
, 50);
封装
每次都写这么多是不是既麻烦又啰嗦,代码还不简洁,于是我封装了如下“timerCheckRun”方法,用的时候只需传入“条件、满足条件时执行的方法、超时提示” 参数即可:
//定时判断执行:
timerCheckRun: function (checkCondition, trueAction, timeOutAction, initRun = true, interval = 50, times = 600) {
var iCount = 0;
var bDoAtInit = false;
var timerId = setInterval((function () {
var fn = function () {
if (bDoAtInit) {
clearInterval(timerId);
return; //初始运行时就已满足条件并执行,则无须开启定时器,关闭定时器即可,无须重复执行
}
if (checkCondition()) {
clearInterval(timerId);
if (initRun) {
if (!timerId) {
bDoAtInit = true; //初始运行时未完成timerId赋值,此时如果已满足条件,则做好标记,定时器中关闭定时执行即可
}
}
trueAction();
} else {
if (++iCount > times) {
clearInterval(timerId);
timeOutAction();
}
}
};
if (initRun) {
fn();
}
return fn;
})(), interval);
}
调用实例:
$JVue.timerCheckRun(
() => _self.fileList.every(x => x.status == 'success') && (_self.cert.AttachFileIDsArray || []).length - (_self.cert.PendingDeleteAttachFileIDsArray || []).length == _self.fileList.length,
() => _self.saveCertInfo(),
() => _self.$message({
message: '上传资质附件超时,未执行保存!',
type: 'error'
})
);
用setTimeout实现同样目的
实际上也可以用setTimeout实现同样的目的,实现起来更简单,只需把主体放在一个自调用函数中,并在函数体中判断条件未达到时定时再执行本函数,代码如下:
var count = 0;
(function checkSave() {
//等待上传执行完成
if (pThis.editForm.AttachFileInfos.every(x => x.status == 'success')) {
setTimeout(() => pThis.doSave(), 20); //wait for running on-success callback for upload
return;
} else {
if (++count > 300) {
pThis.$message({
message: "上传资料执行超时,未执行保存!",
type: 'error'
});
} else {
setTimeout(checkSave, 50);
}
}
})();