如何确保在将函数的值传递给res.render之前已完全执行该函数?

时间:2019-06-22 18:19:31

标签: javascript node.js promise callback

我想解析地址查询并返回地址及其标题,以便 http://localhost:3000/I/want/title/?address=google.com&address=youtube.com将返回: google.com-'google',youtube.com-'youtube'

我正在使用cheerio.js从URL中提取标题,但是这需要时间,并且在变量标题中填充URL标题之前要执行res.render行。如何确保在res.render之前执行我检索标题的代码?

到目前为止,我没有收到任何错误,但是titles []数组没有数据发送到了我的.ejs文件。我尝试通过回调,step.js,async.js解决此问题,但似乎没有任何效果。我已经尝试过使用rsvp.js(promise)来解决它,如下所示(来自app.js),但它也不起作用,titles []仍然为空:

app.get("/I/want/title/", function(req,res){


  if (typeof req.query.address === "string"){
  query = [req.query.address];
}
  else {
  query = req.query.address;
}

  var titles=[];

  var promise = new RSVP.Promise(function(resolve, reject) {
      for (i=0;i<(query.length);i++){
        if (!((query[i]).startsWith("https://www."))){
          var url = "https://www." + query[i];
        }else{
          url=query[i];
        }

        request(url, function (err, resp, body) {
          if (err) {
            var title = "NO RESPONSE"
          } else {
          var $ = cheerio.load(body);
          var title = $("title").text();
        }
          titles.push(title);
        });

      }
      resolve(titles);
      reject();
});

promise.then(function(titles) {
  res.render("title", {url: query, siteName: titles});
}).catch(function() {
  console.log("oh no");
});
});

我的语法或逻辑有问题吗?我应该如何使用回调或Promise执行此操作?

2 个答案:

答案 0 :(得分:0)

您必须在请求回调中放入拒绝和对Promise的承诺,然后您的代码才能正常工作(如下所示)。

app.get('/I/want/title/', function(req, res) {
    if (typeof req.query.address === 'string') {
        query = [req.query.address]
    } else {
        query = req.query.address
    }

    var titles = []

    var promise = new RSVP.Promise(function(resolve, reject) {
        for (i = 0; i < query.length; i++) {
            if (!query[i].startsWith('https://www.')) {
                var url = 'https://www.' + query[i]
            } else {
                url = query[i]
            }

            request(url, function(err, resp, body) {
                if (err) {
                    var title = 'NO RESPONSE'
                    reject()
                } else {
                    var $ = cheerio.load(body)
                    var title = $('title').text()
                }
                titles.push(title)
                resolve(titles)
            })
        }
    })

    promise
        .then(function(titles) {
            res.render('title', {url: query, siteName: titles})
        })
        .catch(function() {
            console.log('oh no')
        })
})

这能回答您的问题吗?

答案 1 :(得分:0)

您的解决方案应位于请求回调的else部分内,拒绝应位于if(err)内部。