在Express应用中有条件地发送回复

时间:2019-06-27 11:42:02

标签: node.js express if-statement

我很好奇您是否可以在Express应用中编写if语句来有条件地执行代码而无需提供else语句。

if(pred) {
  doSomething()
}
return foo;
calcBar(); // doesn't run.

上面是在return语句之后停止执行的同步代码。

我的Express功能如下:

app.get('/matches', async function(req, res) {
  try {
    const data = await someGraphQLCall();
    if(data.length === 0) {
      res.json({ message: "No data." });
    }
    const someOtherData = await someOtherGraphQLCall(data.foo);
    res.json({ someOtherData });
  } catch (err) {
    res.json({err})
  }
}

由于this question,我知道第一个res.json之后的代码可能仍会执行。有办法阻止这种情况吗?如果第一个条件满足,我不希望第二个GraphQL调用执行。不使用else可以做到吗?

编辑:

正如我上面链接的问题所述,使用return语句是一个错误的选择,因为:

  

它也使它的意义和模糊性降低,因为它使用了不正确的语义。如果您未使用该函数中的值,则不应返回一个。

3 个答案:

答案 0 :(得分:3)

您可以在第一个响应上使用return关键字,以立即从函数返回。

app.get('/matches', async function(req, res) {
  try {
    const data = await someGraphQLCall();
    if(data.length === 0) {
      return res.json({ message: "No data." });
    }
    const someOtherData = await someOtherGraphQLCall(data.foo);
    res.json({ someOtherData });
  } catch (err) {
    res.json({err})
  }
} 

编辑:

作为替代方案,您可以拆分数据逻辑并建立响应。这样,您可以使用return,并且更易于阅读:

app.get('/matches', async function (req, res) {
    try {
        const data = await getDataFromGraphQLCall();
        res.json(data);
    } catch (err) {
        res.json({ err })
    }
});

async function getDataFromGraphQLCall() {
    const data = await someGraphQLCall();
    if (data.length === 0) {
        return { message: "No data." };
    }
    const someOtherData = await someOtherGraphQLCall(data.foo);
    return { someOtherData };
}

答案 1 :(得分:2)

如果您想知道没有else的话是否可以实现这一目标,是的。 但是,这可能不是最简单的方法。 IMO,使用return是停止执行控制器的最佳方法。

无论如何,您可以将代码块拆分为中间件,并使用三元运算符有条件地发送响应。

在您的示例中,按如下所示分隔data = await someGraphQLCall();

const middlewareOne = async function(req, res, next) {
    let data = [];
    let response = { message: "No data." };
    try {
        data = await someGraphQLCall();
        req.locals.data = data; // <- attach the data to req.locals
    } catch (err) {
        response = { err };
    }
    data.length === 0 ? res.json(response) : next();
};

然后,将middlewareOne 安装在控制器上

app.get("/matches", middlewareOne, async function controller(req, res) {
    try {
        const someOtherData = await someOtherGraphQLCall(req.locals.data.foo);
        res.json({ someOtherData });
    } catch (err) {
        res.json({ err });
    }
});

这是如何工作的,如果从先前的中间件(在示例中为controller)调用next(),则只能通过express执行middlewareOne函数。
而且由于middlewareOne仅在next()不为0时才调用data.length,因此它将按预期工作。


有关将数据从一种中间件传递到另一种中间件的更多信息,请阅读this

答案 2 :(得分:0)

return语句在此上下文中终止函数执行。我认为,应该先处理成功案例,然后再处理错误案例,因为代码将从上至下读取。

if语句中,数据可以为undefinednull

您可以在此处了解更多信息:MDN - return

app.get('/matches', async function(req, res) {
  try {
    const data = await someGraphQLCall();

    // alternative, if (data && data[0]) {
    if (data && data.length) {
      const someOtherData = await someOtherGraphQLCall(data.foo);
      return res.json({ someOtherData });
    }

    return res.json({ message: "No data." });
  } catch (err) {
    console.log(err); // log error with logger and drain to loggly.
    res.json({ err })
  }
} 

使用Void运算符:

Void运算符使您可以返回未定义的值,但可以计算给定的表达式。

您可以在此处了解更多信息:MDN - Void

app.get('/matches', async function(req, res) {
  try {
    const data = await someGraphQLCall();

    // alternative, if (data && data[0]) {
    if (data && data.length) {
      const someOtherData = await someOtherGraphQLCall(data.foo);
      return void res.json({ someOtherData });
    }

    return void res.json({ message: "No data." });
  } catch (err) {
    console.log(err); // log error with logger and drain to loggly.
    res.json({ err })
  }
}