Javascript 如何在.then.catch链中有条件地运行.then()函数?
我的代码类似于:Javascript 如何在.then.catch链中有条件地运行.then()函数?,javascript,asynchronous,ecmascript-6,promise,es6-promise,Javascript,Asynchronous,Ecmascript 6,Promise,Es6 Promise,我的代码类似于: router.post("/", (req, res, next) => { foo() .then((result) => { res.send(result) }) .catch((error) => { cosnole.log(error) }) //I only want the bar() function and everything below it to run if the first promise is rejected
router.post("/", (req, res, next) => {
foo()
.then((result) => {
res.send(result)
})
.catch((error) => {
cosnole.log(error)
})
//I only want the bar() function and everything below it to run if the first promise is rejected and the first .catch function ran
bar()
.then((data) => {
res.send(data)
})
.catch((error) => {
console.log(error)
})
})
我只希望在第一个承诺被拒绝并且.catch函数启动时,才在它之后运行bar()函数和.then.catch函数
我试过这个:
router.post("/", (req, res, next) => {
rejected = false
foo()
.then((result) => {
res.send(result)
})
.catch((error) => {
rejected = true
console.log(error)
})
if(rejected == true)
bar()
.then((data) => {
res.send(data)
})
.catch((error) => {
console.log(error)
})
})
但是,当捕捉到第一个foo()函数的错误并拒绝承诺时,bar()函数永远不会执行。将调用移到捕捉内部
router.post("/", (req, res, next) => {
foo()
.then((result) => {
res.send(result)
})
.catch((error) => {
cosnole.log(error);
return bar()
.then((data) => {
res.send(data)
})
.catch((error) => {
console.log(error)
});
});
});
试着把你的承诺串起来
router.post("/", (req, res, next) => {
foo()
.then((result) => {
res.send(result)
})
.catch((error) => {
console.log(error);
return bar;
})
.then((data) => {
res.send(data);
})
.catch((error) => {
console.log(error)
});
});
-----------------编辑-----------------
下面是一份可完全测试的ExpressJS示例副本,其中包含您的问题:
const express = require("express");
const app = express();
const port = process.env.PORT || 4000;
app.get("/", function(req, res) {
foo = new Promise(function(resolve, reject) {
// resolve("resolved"); // Uncomment for resolve
reject("rejected");
});
bar = new Promise(function(resolve, reject) {
resolve("myData");
});
foo.then((result) => {
res.send(result);
}).catch((error) => {
console.log(error);
return bar;
}).then((data) => {
res.send(data);
});
});
app.listen(port, function () {
console.log("Listening on port: " + port);
});
考虑到代码的异步性质,
if(rejected==true)
将始终是false
,因为该代码在第一个之前执行,然后是或catch
你可以:
移动.catch()中的所有bar()[…]代码
在.catch()之后移动.then()中的所有条件执行
I/O调用是异步进行的,因此,if
代码在res.send()返回任何响应之前运行。有几种方法可以处理这种情况,下面是另一种使用asyn/await
来编写类似同步的代码的方法:
router.post("/", async (req, res, next) => {
rejected = false
try {
await foo()
.then((result) => {
res.send(result)
})
} catch {
rejected = true
console.log(error)
}
if(rejected == true)
bar()
.then((data) => {
res.send(data)
})
.catch((error) => {
console.log(error)
})
})
正如其他人提到的,您只需要将代码移动到catch
处理程序中
但是,您可能希望简化并更正代码,以
router.post("/", (req, res, next) => {
foo().catch(bar).then(result => {
res.send(result);
, error => {
console.error(error);
res.sendStatus(500); // or next(error) or whatever
});
})
如果您想记录foo
中的错误,即使它们是由bar
处理的,您可能需要
foo().catch(error => {
console.log(error, "(handled by bar)");
return bar();
}).…
承诺不应该解决嵌套回调问题吗?@doodlemeister结构化编程要求对控制流进行嵌套。您仍然可以通过简单的返回链接到它上,@Bergi:嵌套函数不是必需的,即使没有承诺。嵌套/闭包只是管理数据集合的一种惰性方式。我不相信在没有进一步嵌套的情况下,解决这个问题只需要几秒钟。不需要“魔法”。@doodlemeister对于闭包来说,我们总是需要至少一级嵌套,但是是的,我们可以提取命名函数并显式管理作用域环境。内联编写它们更简单,而且通常更可读。@Bergi:闭包并不是真正需要的,但一个级别对于封装只与当前操作相关的函数确实有用。如果使用匿名回调实际上更干净,那么我们将在所有方面都使用它们。相反,我们(至少在我看到的大多数代码中)创建命名函数来组织代码。我不明白为什么异步代码会有什么不同。。。但那只是我。;-)如果您的代码在then()之前执行过,则会得到解析。您确定吗?我在这段代码中看不到任何东西告诉我第二个。那么只有在第一个catch
触发时才会发生。它怎么知道它得到了什么数据呢?嗨,Doodle Meister,我提供了一个服务器示例来回答你的问题。我想知道答案被否决的原因,因为Doodle Meister是正确的。您的代码调用res.send
两次,这是一个错误。未尝试服务器部件,但您得到log(“拒绝”);发送(“myData”)
(当foo拒绝时)或发送(“已解决”);发送(未定义)
(当foo完成时)。颤抖。即使在这里,代码也应该在catch
块中移动。当您使用async
/wait
时,您应该在任何地方都使用它-并且没有单个然后或catch
回调left我没有得到它。我不想得到相同的模式,也不想把事情搞混,但为什么要先在内部使用if
catch
?我建议根本不要使用if
。当您可以直接表达它时,不需要使用控制流标志。我从来没有想过要反转catch/then(更不用说删除重复代码)。这更清晰/可读性更强。(+1)是的,代码在语义上不再严格等同于您的,但是重复的。然后(res.send)
只是请求在链的末尾共享我会这样格式化我的代码,但是bar()函数发送的有效负载与res.send()@SirSudo中的foo()函数的名称不同。你说什么“名称不同”?您应该始终能够将其转换为通用格式。
router.post("/", (req, res, next) => {
foo().catch(bar).then(result => {
res.send(result);
, error => {
console.error(error);
res.sendStatus(500); // or next(error) or whatever
});
})
foo().catch(error => {
console.log(error, "(handled by bar)");
return bar();
}).…