我正在尝试在JS中编写逻辑以在调用序列中突然停止函数执行(无需进一步执行)。检查以下代码。为什么在第二通电话后仍不停止?
function myprom (value) {
return new Promise (function (resolve, reject) {
resolve("I Promise " + value)
})
}
function myfunc (value) {
console.log("Starting in " + value)
}
function terminate() {
setTimeout(() => console.log("Edning"), 1)
}
function dummy() {
console.log("I am not supposed to print anything")
}
async function call() {
await myprom("to end without showing next line")
.then(result => {
myfunc(1) // Call # 1
console.log(result) // Call # 2
terminate() // Call # 3
dummy(1) // Call # 4
terminate() // Call # 5
})
.catch(err => {
console.log(err)
})
}
call()
下面是我的代码的实际输出。
Starting in 1
I Promise to end without showing next line
I am not supposed to print anything
Ending
Ending
期望的是,
Starting in 1
I Promise to end without showing next line
Ending
通常。如何突然停止.then对象内的js执行?
答案 0 :(得分:0)
您可以使用return代替调用终止。那可以解决您的目的。
答案 1 :(得分:0)
当您致电terminate()
这是
function terminate() {
setTimeout(() => console.log("Edning"), 1)
}
setTimeout()
将其回调推至事件循环的未来循环,而在事件循环的当前循环中的其他所有循环都将在此循环之前运行。只有当当前代码链完成并且控制权返回事件循环时,setTimeout()
才有机会运行其回调。
因此,这是代码中发生的事情的顺序:
call()
被执行。myprom()
被执行。这立即解决了其诺言,因此它将在控制权返回事件循环后立即安排其.then()
处理程序运行。.then()
和.catch()
运行。他们目前所做的只是注册一些回调,以便在Promise准备执行它们时稍后再调用。.then()
处理程序。myfunc(1)
运行并输出Starting in 1
console.log(result)
运行并输出I Promise to end without showing next line
terminate()
运行,从现在开始将计时器设置为1毫秒。该函数返回,并且计时器已安排在经过1毫秒后在事件循环的将来时间运行。dummy(1)
被调用,并输出I am not supposed to print anything
。terminate()
被再次调用,并再次安排另一个计时器在事件循环的将来时间间隔内以1ms运行。await
处理承诺并解决async
函数call()
返回的承诺。 await
在这里没有任何用处,也没有人在听call()
返回的承诺。terminate()
设置的第一个计时器开始运行并输出。这样会将控制权返回到事件循环。terminate()
设置的第二个计时器开始运行并投入运行。这样会将控制权返回到事件循环,并且与此代码相关的所有操作都已完成。通常。如何突然停止.then对象内的js执行?
如果您要问的是如何跳过连续调用的其他函数,则通常会使用条件从return
回调中提早分支.then()
。例如,您可以这样做:
async function call() {
await myprom("to end without showing next line")
.then(result => {
myfunc(1) // Call # 1
console.log(result) // Call # 2
if (result === "I Promise to end without showing next line") {
// skip the rest of the code in this callback
return;
}
terminate() // Call # 3
dummy(1) // Call # 4
terminate() // Call # 5
})
.catch(err => {
console.log(err)
})
}
call()
由于您处于.then()
处理程序中,因此您也可以使用throw someError
,这将突然停止.then()
处理程序,就像抛出任何异常会中止当前函数的执行一样。因为这是在.then()
处理程序中,所以该异常将立即被捕获,然后将执行.catch()
处理程序并将其引发的异常传递给它。通常不会将其用于正常的执行路径,因为这通常表示某些错误情况。正常的执行路径更有可能在本地捕获条件,并使用分支或if/else
逻辑或类似的逻辑来决定函数中的哪些代码下一步执行。
请注意,如果您已经启动了一些计时器,则为了防止它们触发,您必须保存timerID
返回的setTimeout()
并在该{{ 1}}取消计时器。
如果您真的想突然停止以停止整个过程,那么在node.js中,您也可以调用clearTimeout()
。
目前还不清楚为什么您认为timerID
的输出和对process.exit()
的第二次调用不会显示在输出中?您打电话给dummy(1)
。 terminate()
函数中的任何内容都不会导致Javascript跳过dummy(1)
处理程序中的其余代码。因此,它继续并同时执行terminate()
和第二个.then()
,因此您会看到两者的输出。
答案 2 :(得分:0)
函数terminate
不会停止执行该函数,而是将其安排在以后至少1秒钟的超时时间内运行。因此,该函数应改为称为delay
。我添加了基于Promise
的实现:
function delay(time = 1) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('Ending');
resolve();
}, time);
})
}
可以等待一个返回标量值的函数。因此,无需使用Promise构造函数包装myProm
。当然,假设myprom
是一个真正的异步操作,而不是一个返回字符串的函数。
function myprom (value) {
return `I Promise ${value}`;
}
使用异步函数时,不需要使用.then
和.catch
进行回调。
async function call() {
try {
const result = await myprom("to end without showing next line")
console.log(result)
myfunc(1)
} catch (e) {
console.error(e);
}
}
具有更改的现有代码段如下所示:
// scalar values can be resolved too
function myprom (value) {
return `I Promise ${value}`;
}
function myfunc (value) {
console.log("Starting in " + value)
}
function delay(time = 1) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('Ending');
resolve();
}, time);
})
}
function dummy() {
console.log("I am not supposed to print anything")
}
async function call() {
try {
const result = await myprom("to end without showing next line")
console.log(result)
myfunc(1)
await delay();
dummy(1);
await delay();
} catch (e) {
console.error(e);
}
return undefined;
}
call();
但是,正如所解释的那样,这不会停止执行流程:
myprom运行
result
已打印
myFunc
执行
1秒的延迟后,将显示一条消息Ending
(因为事件循环没有被许多异步操作阻止)
假人执行
在1秒钟的延迟后,将显示一条消息Ending
该函数返回一个Promise,其值解析为undefined。
当需要终止执行函数时,可以使用delay
来代替return
:
function myprom(value) {
return `I Promise ${value}`;
}
function myfunc(value) {
console.log("Starting in " + value)
}
async function call() {
try {
const result = await myprom("to end without showing next line")
console.log(result)
myfunc(1);
return
} catch (e) {
console.error(e);
}
}
call();