Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/38.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js 在一种情况下使用异步代码的if/else_Node.js_Express_Asynchronous - Fatal编程技术网

Node.js 在一种情况下使用异步代码的if/else

Node.js 在一种情况下使用异步代码的if/else,node.js,express,asynchronous,Node.js,Express,Asynchronous,我在异步代码方面没有太多经验,我遇到了一个问题,以下是我的代码: if (!req.params.user_name) { req.params.user = req.me; } else { User.findOne({username: req.params.user_name}, '_id', (error, user) => { if (error) { return next(error); }

我在异步代码方面没有太多经验,我遇到了一个问题,以下是我的代码:

if (!req.params.user_name) {
    req.params.user = req.me;
} else {
    User.findOne({username: req.params.user_name}, '_id', (error, user) => {
        if (error) {
            return next(error);
        }
        if (!user) {
            let error = new Error('User not found');
            return next(error);
        }
        req.params.user = user;
    });
}
Account.findOne({name: req.params.account_name, created_by: req.params.user})
.populate(['currency', 'created_by'])
.exec((err, account) => {
    if (err) {
        return next(err);
    }
    return res.send(account);
});
正如您所看到的,问题是,在一种情况下,我只需要执行一个简单的过程操作,在另一种情况下,我必须查询异步数据库,然后执行下面的代码。我不能简单地将帐户查询放在用户查询的回调中,因为我不需要一直执行用户查询。 我试图在这里找到答案,但我找到的唯一结果是关于执行一个或另一个异步任务(例如:)。 根据本文的建议,我考虑将代码包装在匿名函数中的if块中,并执行以下操作:

let get_user;
if (!req.params.user_name) {
    let get_user = () => {req.params.user = req.me};
} else {
    let get_user = User.findOne({username: req.params.user_name}, '_id', (error, user) => {
        if (error) {
            return next(error);
        }
        if (!user) {
            let error = new Error('User not found');
            return next(error);
        }
        req.params.user = user;
    });
}
get_user().then(() => {
    Account.findOne({name: req.params.account_name, created_by: req.params.user})
        .populate(['currency', 'created_by'])
        .exec((err, account) => {
            if (err) {
                return next(err);
            }
            return res.send(account);
        });
});
但我觉得这很奇怪,我想我需要从if块中的匿名函数返回一个承诺

那么,解决这个问题的优雅方法是什么呢?我在空闲时间学习node.js,如有任何一般性建议,将不胜感激


谢谢您的时间。

回调不应与猫鼬一起使用;它长期以来一直支持承诺

这个

无法工作,因为
get\u用户
需要返回承诺

通常是这样做的:

let userPromise;
if (!req.params.user_name) {
    userPromise = Promise.resolve(req.me);
} else {
    userPromise = User.findOne(...);
}
userPromise().then((user => {
    req.params.user = user;

    return Account.findOne(...);
});
请注意,
req.params.user
是这两种情况的通用代码。这可以通过
async..wait
方便地完成,它是承诺的语法糖:

try {
    let user;
    if (!req.params.user_name) {
        user = req.me;
    } else {
        user = await User.findOne({username: req.params.user_name}, '_id');
    }

    req.params.user = user;

    const account = await Account.findOne({name: req.params.account_name, created_by: req.params.user})
        .populate(['currency', 'created_by'])
        .exec();

    res.send(account);
} catch (err) {
    next(err);
}
这应该是一个
async
中间件函数的主体,在原始代码中没有显示


正如中所解释的,Express本身不支持承诺,所有的
async
中间件和路由处理程序都应该用
try..catch
包装以进行错误处理。

好的,昨天我做了一些类似的事情来实现它:if(!req.params.user_name){get_user=()=>{return new Promise((resolve)=>{对于else块也是这样,然后执行“get_user()。然后(()=>{”通过阅读您的代码,我发现我不需要在if块中实例化承诺,只需静态调用它,也不需要将其封装在匿名函数中,在else块中我将解析User.findOne的结果。您确认了吗?将同步代码放入其中对我来说有点不安一个承诺,但它现在更有意义。至于async..Wait示例,这是否意味着如果我不进行回调,User.findOne将自动返回结果,如果有回调,将自动抛出错误?这将非常好,而且更直观,因为它看起来像同步代码。感谢您的解释,它确实清除了是的,你根本不需要匿名函数。你需要
承诺。如果你使用原始承诺,解决
,因为你需要与
链接的东西,那么
,这就是为什么在第一个代码段中有
userPromise
。User.findOne返回结果的承诺。
wait
是语法糖对于.
then(result=>/*handle result*/,err=>/*抛出错误*)
。两个代码段在功能上是等效的,第二个代码段看起来更简单。由于您使用的是支持async/await的Node,我建议使用async/await。好的,我将尝试使用async。await,这将允许我清除所有地方的大量嵌套回调。谢谢您的时间。
try {
    let user;
    if (!req.params.user_name) {
        user = req.me;
    } else {
        user = await User.findOne({username: req.params.user_name}, '_id');
    }

    req.params.user = user;

    const account = await Account.findOne({name: req.params.account_name, created_by: req.params.user})
        .populate(['currency', 'created_by'])
        .exec();

    res.send(account);
} catch (err) {
    next(err);
}