如何根据异步调用的持续时间设置 JS 变量
How to set a JS variable depending on the duration of an asynchronous call
我有这个:
this.toggleWaiting()
this.results = await this.query(term)
this.toggleWaiting()
首先触发加载微调器。
然后查询运行。
当查询函数结束时,加载微调器将关闭。
但是如果我只想显示加载微调器,当查询可能需要超过 0.5 秒时怎么办?
有没有简单的方法可以做到这一点?
实现此目的的一种方法是将 this.query(term)
承诺传递给一个函数,该函数将仅在查询花费的时间超过指定的时间量(使用超时)时处理触发 toggleWaiting
.
例如,下面有一个承诺,一个将以 isWaiting
状态调用的函数 (waitingFn
) 以及一个可以用来指定的 timeout
在显示加载微调器之前要等待多长时间。最后,当承诺已经实现时,我们 return 结果:
async function handleWaiting(promise, waitingFn, timeout) {
let loadingStarted = false;
let timeoutInstance = null;
const timeoutPromise = new Promise((res) => {
timeoutInstance = setTimeout(() => {
loadingStarted = true;
waitingFn(true);
}, timeout);
return res();
});
function onFinished() {
clearTimeout(timeoutInstance);
if (loadingStarted) {
waitingFn(false);
}
}
try {
const [result] = await Promise.all([promise, timeoutPromise]);
onFinished();
return result;
} catch (ex) {
onFinished();
throw ex;
}
}
您可以像这样调用 handleWaiting
函数:
const result = await handleWaiting(this.query(term), (isWaiting) => this.toggleWaiting(), 500);
正如@FZs 和@Bergi 所指出的(谢谢你们),以下是由于使用 promise 构造函数而导致的反模式:
function handleWaiting(promise, waitingFn, timeout) {
return new Promise((res, rej) => {
let loadingStarted = false;
const timeoutInstance = setTimeout(() => {
loadingStarted = true;
waitingFn(true);
}, timeout);
function onFinished() {
if (loadingStarted) {
waitingFn(false);
}
clearTimeout(timeoutInstance);
}
return promise
.then((result) => {
onFinished();
res(result);
})
.catch((ex) => {
onFinished();
rej(ex);
});
});
}
感谢 ljbc1994,我找到了一个很好的解决方案。
在我的 alpineJs 对象中 - 我有这个实现:
{
waiting: false,
async handleWaiting(promise, timeout) {
return new Promise((res, rej) => {
let loadingStarted = false;
const timeoutInstance = setTimeout(() => {
loadingStarted = true;
this.waiting = true;
}, timeout);
const onFinished = () => {
if (loadingStarted) {
this.waiting = false;
}
clearTimeout(timeoutInstance);
}
promise
.then((result) => {
onFinished();
res(result);
})
.catch((ex) => {
onFinished();
rej(ex);
});
});
},
async searchForTerm(term) {
this.results = await this.handleWaiting(this.$wire.query(term), 500);
// do something with the results...
},
}
非常简单。
对于对完整代码感兴趣的人 - 这是 github 存储库中的提交:
https://github.com/MichaelBrauner/sunfire-form/commit/7c1f8270e107a97b03264f5ddc5c3c3ae6f7cfd7
我有这个:
this.toggleWaiting()
this.results = await this.query(term)
this.toggleWaiting()
首先触发加载微调器。 然后查询运行。 当查询函数结束时,加载微调器将关闭。
但是如果我只想显示加载微调器,当查询可能需要超过 0.5 秒时怎么办?
有没有简单的方法可以做到这一点?
实现此目的的一种方法是将 this.query(term)
承诺传递给一个函数,该函数将仅在查询花费的时间超过指定的时间量(使用超时)时处理触发 toggleWaiting
.
例如,下面有一个承诺,一个将以 isWaiting
状态调用的函数 (waitingFn
) 以及一个可以用来指定的 timeout
在显示加载微调器之前要等待多长时间。最后,当承诺已经实现时,我们 return 结果:
async function handleWaiting(promise, waitingFn, timeout) {
let loadingStarted = false;
let timeoutInstance = null;
const timeoutPromise = new Promise((res) => {
timeoutInstance = setTimeout(() => {
loadingStarted = true;
waitingFn(true);
}, timeout);
return res();
});
function onFinished() {
clearTimeout(timeoutInstance);
if (loadingStarted) {
waitingFn(false);
}
}
try {
const [result] = await Promise.all([promise, timeoutPromise]);
onFinished();
return result;
} catch (ex) {
onFinished();
throw ex;
}
}
您可以像这样调用 handleWaiting
函数:
const result = await handleWaiting(this.query(term), (isWaiting) => this.toggleWaiting(), 500);
正如@FZs 和@Bergi 所指出的(谢谢你们),以下是由于使用 promise 构造函数而导致的反模式:
function handleWaiting(promise, waitingFn, timeout) {
return new Promise((res, rej) => {
let loadingStarted = false;
const timeoutInstance = setTimeout(() => {
loadingStarted = true;
waitingFn(true);
}, timeout);
function onFinished() {
if (loadingStarted) {
waitingFn(false);
}
clearTimeout(timeoutInstance);
}
return promise
.then((result) => {
onFinished();
res(result);
})
.catch((ex) => {
onFinished();
rej(ex);
});
});
}
感谢 ljbc1994,我找到了一个很好的解决方案。
在我的 alpineJs 对象中 - 我有这个实现:
{
waiting: false,
async handleWaiting(promise, timeout) {
return new Promise((res, rej) => {
let loadingStarted = false;
const timeoutInstance = setTimeout(() => {
loadingStarted = true;
this.waiting = true;
}, timeout);
const onFinished = () => {
if (loadingStarted) {
this.waiting = false;
}
clearTimeout(timeoutInstance);
}
promise
.then((result) => {
onFinished();
res(result);
})
.catch((ex) => {
onFinished();
rej(ex);
});
});
},
async searchForTerm(term) {
this.results = await this.handleWaiting(this.$wire.query(term), 500);
// do something with the results...
},
}
非常简单。
对于对完整代码感兴趣的人 - 这是 github 存储库中的提交:
https://github.com/MichaelBrauner/sunfire-form/commit/7c1f8270e107a97b03264f5ddc5c3c3ae6f7cfd7