Node.js AJAX路由在评估引用的函数之前返回数据

Node.js AJAX route returns data before referenced function is evaluated

本文关键字:函数 返回 数据 引用 AJAX js 路由 评估 Node      更新时间:2023-09-26

更新

工作了,但我仍然认为有问题。只有当我将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"}]

不能只从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});
  });
});