代码之家  ›  专栏  ›  技术社区  ›  Eunicorn

Node.js在另一个方法完成后调用一个方法

  •  0
  • Eunicorn  · 技术社区  · 7 年前

    我想在“app.get('/news/api/:newsName',函数(req,res)”完成后调用“app.get('/news/news desc',(req,res)”方法。

    这是我的代码:

    let articleUrlArray = [];
    
    app.get('/news/api/:newsName', function(req, res) {
      const API_KEY = 'example';
    
      let data = '';
    
      const techCrunchURL = `https://newsapi.org/v2/top-headlines?sources=techcrunch&apiKey=${API_KEY}`
    
      switch(req.params.newsName) {
        case 'tech-crunch':
          request(techCrunchURL, function(err, response, html) {
        
            let formattedData = JSON.parse(response.body);
    
            for(let i = 0; i < formattedData.articles.length; i++) {
              articleUrlArray.push(formattedData.articles[i].url);
            }
    
            data = response.body;
            res.setHeader('Content-Type', 'application/json');
            res.send(data);
          });
    
          break;
    
        default:
          data = 'Please type in correct news source';
          break;
      }
    })
    
    const checkBody = res => (err, response, html) => {
        const $ = cheerio.load(html);
        const articleContent = $('.article-content').children('p')
        const bodyOne = articleContent.eq(0).text()
        const bodyTwo = articleContent.eq(1).text()
        const isExtensive = bodyOne.split(' ').length > 50
        res(isExtensive ? { bodyOne } : { bodyOne, bodyTwo })
    }
    
    const getArticle = article => new Promise(res => request(article, checkBody(res)))
    
    app.get('/news/news-desc', (req, res) => {
        Promise.all(articleUrlArray.map(getArticle)).then(data => res.send(JSON.stringify(data)))
    })

    如您所见,第一个方法调用“newsapi.org”,得到10篇文章。然后它只提取这些文章的url并将它们推送到articleUrlArray中。

    将url推入articleUrlArray之后,它将如下所示:

    let articleUrlArray = [ 'https://techcrunch.com/2018/05/19/shared-housing-startups-are-taking-off/',
      'https://techcrunch.com/2018/05/19/shared-housing-startups-are-taking-off/',
      'https://techcrunch.com/2018/05/19/my-data-request-lists-guides-to-get-data-about-you/',
      'https://techcrunch.com/2018/05/19/siempos-new-app-will-break-your-smartphone-addiction/',
      'https://techcrunch.com/2018/05/19/la-belle-vie-wants-to-compete-with-amazon-prime-now-in-paris/',
      'https://techcrunch.com/2018/05/19/apple-started-paying-15-billion-european-tax-fine/',
      'https://techcrunch.com/2018/05/19/original-content-dear-white-people/',
      'https://techcrunch.com/2018/05/19/meet-the-judges-for-the-tc-startup-battlefield-europe-at-vivatech/',
      'https://techcrunch.com/2018/05/18/nasas-newest-planet-hunting-satellite-takes-a-stellar-first-test-image/',
      'https://techcrunch.com/video-article/turning-your-toys-into-robots-with-circuit-cubes/',
      'https://techcrunch.com/2018/05/18/does-googles-duplex-violate-two-party-consent-laws/' ];

    它只会被url填满。

    然后第二个方法,将使用填充的articleUrlArray来做自己的事情。

    但是,目前对于我的代码,第二个方法在articleUrlArray被填充之前首先运行。

    我想在第一个方法完成并且articleUrlArray已填充了url之后运行第二个方法。

    你能帮我做这个吗?

    2 回复  |  直到 7 年前
        1
  •  0
  •   Hugo Nasciutti    7 年前
    let articleUrlArray = [];
    const addArticleUrl = url => articleUrlArray.push(url)
    
    const checkBody = res => (err, response, html) => {
      const $ = cheerio.load(html);
      const articleContent = $('.article-content').children('p')
      const bodyOne = articleContent.eq(0).text()
      const bodyTwo = articleContent.eq(1).text()
      const isExtensive = bodyOne.split(' ').length > 50
      res(isExtensive ? { bodyOne } : { bodyOne, bodyTwo })
    }
    
    const getArticle = article => new Promise(res => request(article, checkBody(res)))
    
    const newsDescMiddleware = app.get('/news/news-desc', (req, res) => {
      Promise.all(articleUrlArray.map(getArticle)).then(data => res.send(JSON.stringify(data)))
    })
    
    const techCrunch = res => url => request(url, (err, response, html) => {
      let formattedData = JSON.parse(response.body);
      formattedData.articles.forEach(article => addArticleUrl(article.url))
      res(response.body)
    })
    
    const getNewsByName = (newsName, url) => new Promise((res, reject) => ({
      'tech-crunch': techCrunch(res)(url)
    }[newsName])) || reject()
    
    const getNewsByNameMiddleware = (req, res) => {
      const API_KEY = 'example';
      const techCrunchURL = `https://newsapi.org/v2/top-headlines?sources=techcrunch&apiKey=${API_KEY}`
    
      getNewsByName(req.params.newsName, url)
        .then(body => {
          res.setHeader('Content-Type', 'application/json');
          res.send(body)
        })
        .catch(() => res.send('Please type in correct news source'))
    }
    
    app.get('/news/api/:newsName', getNewsByNameMiddleware, newsDescMiddleware)
    

    在这里,我给你做了一些中间产品。

    我假设您不需要前一个中间件的响应。

    我喜欢按职责划分代码,并按功能编写代码。

        2
  •  0
  •   Cisco    7 年前

    如果您愿意的话,您可以将第一条函数路由的核心逻辑分离出来,并在这两个地方重用它。但是,您仍然需要提供newsName参数来获取'/news/news desc'端点。

    代码示例。

        let articleUrlArray = [];
    
        function getNewsNames(newsName, callback) {
            const API_KEY = 'example';
            let data = '';
            const techCrunchURL = `https://newsapi.org/v2/top-headlines?sources=techcrunch&apiKey=${API_KEY}`
    
            switch (newsName) {
                case 'tech-crunch':
                    request(techCrunchURL, function (err, response, html) {
    
                        let formattedData = JSON.parse(response.body);
    
                        for (let i = 0; i < formattedData.articles.length; i++) {
                            articleUrlArray.push(formattedData.articles[i].url);
                        }
    
                        data = response.body;
                        callback(null, data);
                    });
    
                    break;
    
                default:
                    data = 'Please type in correct news source';
                    callback('Error', data);
                    break;
            }
        }
    
        app.get('/news/api/:newsName', function (req, res) {
    
            getNewsNames(req,params.newsName, (err, data) => {
                if (!err) {
                    res.setHeader('Content-Type', 'application/json');
                }
    
                return res.send(data);
            })
        })
    
        const checkBody = res => (err, response, html) => {
            const $ = cheerio.load(html);
            const articleContent = $('.article-content').children('p')
            const bodyOne = articleContent.eq(0).text()
            const bodyTwo = articleContent.eq(1).text()
            const isExtensive = bodyOne.split(' ').length > 50
            res(isExtensive ? { bodyOne } : { bodyOne, bodyTwo })
        }
    
        const getArticle = article => new Promise(res => request(article, checkBody(res)))
    
        app.get('/news/news-desc/:newsName', (req, res) => {
            getNewsNames(req.params.newsName, (err, data) => {
                // by now, the articleUrlArray array will be filled
                Promise.all(articleUrlArray.map(getArticle)).then(data => res.send(JSON.stringify(data)))
            })
        })