【问题标题】:NodeJS: Should I Use a Promise to Peform Preprocessing?Node JS:我应该使用 Promise 来执行预处理吗?
【发布时间】:2020-06-30 20:30:01
【问题描述】:

NodeJS + Express。我正在努力实现以下目标:

  • 客户端使用以下 JSON 文档 data={text: "I love Stackoverflow", shouldPreprocess: <true or false>} 发送 post 请求;
  • 我需要调用外部 WebSocket 服务对文本进行情感分析并将结果返回为 JSON,例如{sentiment: '正面'};
  • 但是,如果 shouldPreprocess 为 true,我应该先调用另一个预处理服务;

问题:

  1. 我不确定执行此操作的正确方法是什么,但这里有两次尝试。我觉得他们俩都很老套。
  2. 我不确定如何处理来自客户端的无效输入。详情如下。
router.post('/analyse', function (req, res, next) {
    const data = req.body;

    if (typeof data.text === 'undefined' || typeof data.shouldPreprocess === 'undefined') {
        return next(new Error('Please provide text and flag'));
    }

    analyseSentiment(data.text, data.shouldPreprocess)
        .then(doc => res.json(doc))
        .catch(err => next(err));
});

function analyseSentiment(text, shouldPreprocess) {
    let promise;
    if (shouldPreprocess === true) {
        textP = preprocess(text);
    } else promise = new Promise((res, req) => res(text));
    return textP
        .then(text => axios.post(<URL to sentiment analyser>, text))

function preprocess(text) {
    const ws = WebSocket(<URL of preprocessor>);
    // But what if I wanted to check for some property of text here and throw an error
    // that gets sent to the client, just as I do in the main function, i.e. in router.post above?
    ws.on('open', () => ws.send(text));
    return new Promise((res, rej) => ws.on('message', preprocText => res(preprocText)));
}

所以这是第一种方式。感觉很奇怪,因为我在 analyseSentiment 中创建了一个只返回文本的无用承诺,这样我就有了一种统一的方式来处理预处理和非预处理场景。另请参阅上面函数preprocess 中的评论中的问题。

第二种方法是在router.post 中做所有事情,例如:

router.post('/analyse', function (req, res, next) {
    const data = req.body;

    if (typeof data.text === 'undefined' || typeof data.shouldPreprocess === 'undefined') {
        return next(new Error('Please provide text and flag'));
    }

    if (data.shouldPreprocess) {
        preprocess(data.text)
            .then(text => axios.post(<URL to sentiment analyser>, text)))
            .then(doc => res.json(doc))
            .catch(err => next(err));
    } else {
        axios.post(<URL to sentiment analyser>, text)
            .then(doc => res.json(doc))
            .catch(err => next(err));
    }

});

但是当然有重复的代码片段。

谢谢!

【问题讨论】:

    标签: javascript node.js express websocket promise


    【解决方案1】:

    我会利用在 Express 中可以将多个函数作为请求处理程序传递的事实。当你不带参数地调用next() 时,它们将被一个接一个地调用。

    示例实现:

    router.post('/analyse', validate, preprocess, analyse)
    
    function validate (req, res, next) {
      let text = req.body.text
      let preprocess = req.body.shouldPreprocess
      if (typeof text === 'string' &&
          text.length > 0 &&
          text.length < 400 &&
          typeof preprocess === 'boolean') {
        next() // validation complete, go to the next request handler
      } else {
        return res.status(400).json({ reason: 'Please provide text and flag' })
      }
    }
    
    function preprocess (req, res, next) {
      if (req.body.shouldPreprocess) {
        const ws = WebSocket(<URL of preprocessor>)
    
        ws.on('open', () => ws.send(text))
        ws.on('message', preprocessed_text => {
          // check for some properties of text
          // this function is not implemented here
          if (validatePreprocessedText(preprocessed_text) {
            // send error to client
            return res.status(400).json({ reason: 'Malformed preprocessing result.' })
          }
          // seems legit, go on...
          res.locals.text_to_analyze = preprocessed_text
          next()
        }
        ws.on('error', next) // or return res.status(500).json({ reason: 'whatever...' })
      } else {
        res.locals.text_to_analyze = req.body.text
        next() // nothing to see here, move on...
      }
    }
    
    function analyse (req, res, next) {
      axios.post(<URL to sentiment analyser>, res.locals.text_to_analyze)
        .then(reply => res.json(reply.data))
        .catch(error => {
          console.log(error)
          res.status(500).json({ reason: 'Sentiment service has blown up.' })
        })
    }
    

    我希望这会有所帮助! :)

    【讨论】:

    • 很有意义,非常感谢。我接受另一个回复的原因是它是先发布的 - 想法是一样的。
    【解决方案2】:

    您可能希望将预处理和验证解耦为express middlewares,并将它们放在主处理程序的前面,这可能如下所示:

    const validate = (req, res, next) => {
      const data = req.body;
    
      if (typeof data.text === 'undefined' || typeof data.shouldPreprocess === 'undefined') {
        return next(new Error('Please provide text and flag'));
      }
      return next();
    }
    
    const preprocess = (req, res, next) => {
      if (req.body.shouldPreprocess) {
        const ws = WebSocket('<URL of preprocessor>');
        ws.on('message', preprocText => {
          req.body.text = preprocText;
          next();
        });
      } else {
        next()
      }
    }
    
    router.post('/analyse', validate, preprocess, function (req, res, next) {
      const text = req.body.text;
    
      axios.post('<URL to sentiment analyser>', text)
        .then(doc => res.json(doc))
        .catch(err => next(err));
    });
    

    【讨论】:

      猜你喜欢
      • 2010-09-30
      • 1970-01-01
      • 2017-04-16
      • 2016-05-08
      • 1970-01-01
      • 1970-01-01
      • 2021-01-23
      • 1970-01-01
      • 2018-06-12
      相关资源
      最近更新 更多