PDN*_*PDN 3 javascript node.js promise express es6-promise
当我在服务器上收到发布请求以创建新游戏时,我会执行几个查询.首先,我搜索用户是否已经在游戏中,如果是,则返回游戏.否则,我搜索一个开放的游戏,其中某人正在等待对手并返回该游戏,如果是这样的话.最后,如果没有找到上述状态的游戏,我会创建一个新游戏并返回.所以我的代码看起来像这样:
.post( function(req, res, next){
...findUsersExistingGame...
.then(function(game){
if(game){ return res.send(game); }
else{
return ...findUserWaitingForOpponentsGame...
}
}
.then(function(game){
if(game){ return res.send(game); }
else{
return ...createNewGame...
}
})
.then(function(game){
return res.send(game);
})
.catch(function(err){
return next(err);
});
Run Code Online (Sandbox Code Playgroud)
我最终会将每个函数重构为辅助函数以提高可读性,但我需要首先弄清楚链接.我的问题是,如果我找到一个游戏中的承诺早链(即有两种用户的现有游戏或谁是等待对手的另一个用户)然后我返回res.send(游戏); 但是,第三个.then将抛出一个错误,因为我之前的.then()语句返回undefined.如果我想做一个res.send(游戏),我如何早早退出承诺链?
选项1:我已经看到了抛出错误并明确捕获它的建议,但这种感觉从根本上说是错误的,使用错误来控制流量.
选项2:我可以做类似的事情而不是链接承诺,但这类似于"承诺/回调地狱":
.post( function(req, res, next){
...findUsersExistingGame...
.then(function(game){
if(game){ return res.send(game); }
else{
...findUserWaitingForOpponentsGame...
.then(function(game){
if(game){ return res.send(game); }
else{
return ...createNewGame...
.then(function(game){
return res.send(game);
});
}
})
}
}
Run Code Online (Sandbox Code Playgroud)
还有另一种方式(最好是在ES5中,因为我仍然试图从根本上理解承诺,但ES6的答案也是受欢迎的)?
这里的主要问题是,沿途的每个步骤都有三个可能的返回值:
由于promises只是自然地分离错误而没有错误,只要你想以不同的方式处理这三个单独的返回中的每一个,你就会添加一些自己的分支逻辑.
要使用promise结果干净地进行分支需要额外的嵌套级别,并且通常没有理由避免它,因为它将使您的代码最容易遵循并理解其逻辑.
.post( function(req, res, next) {
findUsersExistingGame(...).then(function(game) {
if (game) return game;
return findUserWaitingForOpponentsGame(...).then(function(game) {
if (game) return game;
// createNewGame() either resolves with a valid game or rejects with an error
return createNewGame(...);
});
}).then(function(game) {
res.send(game);
}, function(err) {
// send an error response here
});
});
Run Code Online (Sandbox Code Playgroud)
请注意这是如何简化每个阶段的返回,并返回下一个嵌套的承诺,使事物链,并集中处理将响应发送到一个地方以减少整体代码.
现在,您可以通过让每个函数接受之前的游戏值并让他们检查是否已经存在有效游戏来隐藏其中一些逻辑,如果是,则他们什么也不做:
.post( function(req, res, next) {
findUsersExistingGame(args)
.then(findUserWaitingForOpponentsGame)
.then(createNewGame)
.then(function(game) {
res.send(game);
}, function(err) {
// send an error response here
});
});
Run Code Online (Sandbox Code Playgroud)
但是,在内部findUserWaitingForOpponentsGame(),你必须接受findUsersExistingGame()解决的确切论据,你必须检查游戏是否有效.
function findUserWaitingForOpponentsGame(args) {
if (args.game) {
return Promise.resolve(args);
} else {
return doAsyncFindUserWaitingForOpponentsGame(args);
}
}
Run Code Online (Sandbox Code Playgroud)
每个函数都将使用args对象解析,该对象上有任何公共参数,并且具有.game每个级别可以检查的属性.虽然这为您提供了一个很好的清洁控制流,但它确实在每个函数中创建了额外的代码,它强制每个函数接受作为前一个函数输出的参数(因此您可以直接链接).你可以决定哪个更好.
| 归档时间: |
|
| 查看次数: |
1339 次 |
| 最近记录: |