2

更新

搞定了,但我还是觉得有问题。如果我将 setTimeout 计时器设置为非常长(如 2000),我只会得到正确的返回数据。如果我将其设置为 200,则回调函数将使用空数据执行,因为尚未返回 API 调用。

我已经更新了下面的代码。

设置:

我通过 AJAX (jQuery) 从前端发送一个 get 值,然后使用该值调用 Foursqaure API 以获取相关场所的列表。

除了事件的顺序变得混乱之外,这工作“很好”。当我将 GET 值插入到要评估的函数的参数中时,我得到了一个我不需要的返回值,然后导致模板在我的函数的另一个返回值之前呈现在前端 -我想要的——给了。

实际上,我认为它实际上并没有被退回。刚刚登录到控制台。

问题:

如何通过 AJAX 在places.js 中的initGetVenues 函数末尾将过滤后的JSON 对象列表返回到前端?

语境:

我正在使用这个包连接到 Foursquare: https ://npmjs.org/package/foursquarevenues

前端的 AJAX 调用

    $("#search-items").submit(function() {
        var placeQuery = $("#search-input").val();

        $.ajax({
            url: '/return/places/',
            data: {"passPlaceQuery": placeQuery},
            type: 'get',
            dataType: 'html',
            success: function(data) {
                $("#search-results-list").html(data);
            },
        });

        return false;
    });

index.js [更新]

returnPlaces: function(req, res) {
  if (req.headers['x-requested-with'] === 'XMLHttpRequest') {
    console.log("I've started routing");

    return places.findVenue({
      ll: "38.214986,-85.637054",
      radius: 32186,
      query: req.query.passPlaceQuery,
      intent: "browse",
      categoryId: "4bf58dd8d48988d1e0931735"
    }, function(err, data) {
      console.log("Venue callback");

      if (err) {
        res.send(500);
      }

      console.log("Attempting render: " + data);
      return res.render("place-results", {
        layout: false,
        foundPlaces: data
      });

    });
  } else {
    return res.redirect("/");
  }
}

places.js [更新]

(function() {
  var foursquare, initGetVenues;

  foursquare = (require('foursquarevenues'))('SECRET', 'SECRET');

  module.exports = {
    findVenue: initGetVenues = function(criteria, callback) {
      var jsonUniquePlaces;
      jsonUniquePlaces = [];

      foursquare.getVenues(criteria, function(error, venues) {
        var i, objUniquePlace, range, uniquePlaces, venueName;

        if (!error) {
          range = Object.keys(venues.response.venues).length;
          uniquePlaces = [];
          i = 0;
          while (i < range) {
            venueName = venues.response.venues[i].name;
            if (!(uniquePlaces.indexOf(venueName) > -1)) {
              uniquePlaces.push(venueName);
            }
            i++;
          }
          i = 0;
          while (i < uniquePlaces.length) {
            objUniquePlace = {
              place: uniquePlaces[i]
            };
            jsonUniquePlaces.push(objUniquePlace);
            i++;
          }
          jsonUniquePlaces = JSON.stringify(jsonUniquePlaces);

          return jsonUniquePlaces;
        }
      });

      return setTimeout((function() {
        return callback(null, jsonUniquePlaces);
      }), 200);
    }
  };

}).call(this);

当 setTimeout 为 2000 时,我得到:

| I've started routing
| [{"place":"Quills Coffee"},{"place":"Quills Coffe"},{"place":"Quill's Coffee"}]
| Venue callback
| Attempting render: [{"place":"Quills Coffee"},{"place":"Quills Coffe"},{"place":"Quill's Coffee"}]
| GET /return/places/?passPlaceQuery=quills 200 2009ms - 150

当 setTimeout 为 200 时,我得到:

| I've started routing
| Venue callback
| Attempting render: 
| GET /return/places/?passPlaceQuery=quills 200 210ms - 11
| [{"place":"Quills Coffee"},{"place":"Quills Coffe"},{"place":"Quill's Coffee"}]
4

1 回答 1

2

你不能只从内部返回你的值findVenue。调用foursquare.getVenues是异步的。因此,当节点引擎到达函数调用foursquare.getVenues(opt, callback)时,它只是启动操作并继续执行任何进一步的语句,然后 index.js 继续执行,然后您呈现响应......最后一段时间后,foursquare.getVenues代码调用它的回调(大概是当它已经完成了与foursquare API的对话。)

您需要重写places.findVenue以获取回调参数。当您调用时,places.findVenue()您将传递一个函数以作为回调执行。是您应该发送响应的时间。

这是一个您可以扩展的简化示例:

function findVenue(opt, callback){
  setTimeout(function(){
    console.log('Done with foursquare.getVenues, calling back to routing function')
    callback(null, opt);   
    // you passs this callback function to setTimeout. it executes it in 200ms
    // by convention, pass a null error object if successful
  }
  ,200);
};


app.get('/return/places', function(req, res){
  console.log('routing function start');
  findVenue({
    lat:40, 
    lng: 70, 
    query: 'foo'
  }, function(err, data){
    console.log('findVenue callback');
    if(err){ return res.send(500) };
    res.render('template', {foo: data});
  });

});
于 2013-07-18T07:07:36.570 回答