Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript for循环中的异步函数运行太慢。如何提高性能?_Javascript_Angularjs_Node.js_Google Maps - Fatal编程技术网

Javascript for循环中的异步函数运行太慢。如何提高性能?

Javascript for循环中的异步函数运行太慢。如何提高性能?,javascript,angularjs,node.js,google-maps,Javascript,Angularjs,Node.js,Google Maps,在我正在开发的应用程序中,我用鼠标点击谷歌地图绘制了一个圆圈。鼠标单击设置圆的中心。圆的半径为0.5英里。通过使用,我进行异步调用以查找0.5英里半径内的路线。每个圆圈通常有多条路线。然后,我在每一条路线上为最近的公共汽车站做了一个标记,只在这个圆圈内的一个方向上(只在南行或北行)。问题是,;它工作得很慢。我将我的findClosestStop函数的时间复杂度从n更改为log(n),希望它能带来显著的不同。虽然有点不同,但是放置所有标记需要4到10秒的时间,这取决于附近路线的数量。这是我使用No

在我正在开发的应用程序中,我用鼠标点击谷歌地图绘制了一个圆圈。鼠标单击设置圆的中心。圆的半径为0.5英里。通过使用,我进行异步调用以查找0.5英里半径内的路线。每个圆圈通常有多条路线。然后,我在每一条路线上为最近的公共汽车站做了一个标记,只在这个圆圈内的一个方向上(只在南行或北行)。问题是,;它工作得很慢。我将我的
findClosestStop
函数的时间复杂度从
n
更改为
log(n)
,希望它能带来显著的不同。虽然有点不同,但是放置所有标记需要4到10秒的时间,这取决于附近路线的数量。这是我使用NodeJS和AngularJS的第一个项目。在这个项目之前,我只熟悉JavaScript的语法。我想知道我能做些什么来加快这项工作?我是不是犯了一个概念上的错误?当我等待答案时,我会将(查找最近的停止点)功能移到后端,以查看它是否会对性能产生影响,尽管我不这么认为,因为将有相同的计算量

如果你需要更多信息,请告诉我。期待听到一些关于这方面的反馈。提前谢谢

controller.js

    ...

        var distance = new distance.Distance();

    ...
        function createGTFSCluster(name, lat, lng, walk, bike, map) {
            var deferred = $q.defer();

            var clusterCenter = new graph.Center(lat, lng, map);
            var cluster = new graph.NodeCluster(clusterCenter, walkRadius, bikeRadius);

            cluster.setName(name);

            getRoutesNearby(cluster.clusterCenter, cluster.bikeRadius)
                .then(function(results) {
                    // Set the cluster's nearby routes
                    var routes = results[0];
                    cluster.nearbyRoutes = routes;
                    angular.forEach(routes, function(route, index){
                        getStopsByRoute(agency_key,route.route_id, 1).then(function(json){
                                            console.log(index, '->', route.route_id);
                            var stops = json[0];
                            var closestStop = distance.getClosestStop(stops, cluster);
                            cluster.setNodes(closestStop, route);
                        })
                    });
                        // Set the cluster's nodes to the stops found
                        deferred.resolve(cluster);
                });

            return deferred.promise;
        }
    ...


    // Retrieves the routes near a certain point on the map
        //
        // Input: cluster - A node cluster on the map we are finding routes for
        // Output: A promise whose results are the nearby route IDs
        function getRoutesNearby(center, radius) {
            var deferred = $q.defer();

            // Query the GTFS service for nearby routes and draw them
            gtfs.getRoutesByLocation(agency_key, center.lat, center.lon, radius)
                .then(function(json) {
                    //Get all route objects not only IDs
                    var routes = [];
                    for(index in json){
                        routes.push(json[index]);
                    }

                    // We got the routes, resolve
                    deferred.resolve(routes);
                });

            return deferred.promise;
        }
...

    function getStopsByRoute(agency_key, route_id, direction_id){
        var deferred = $q.defer();
        gtfs.getStopsByRoute(agency_key, route_id, direction_id)
            .then(function(json){ //all stops on the route in one direction
                var stopsArr =[];
                stopsArr.push(json.data[0].stops);
                deferred.resolve(stopsArr);
            });
            return deferred.promise;
    }
    Distance.prototype.getClosestStop = function (stops, cluster){
      var closestStop = findClosestStop(stops, cluster);
      return closestStop;
    }

  function findDistance(stopObj, clusterObj){

    var stopCenter = {
      lat:stopObj.stop_lat,
      lon:stopObj.stop_lon
    };
    var clusterCenter = clusterObj.clusterCenter;

    var lat1 = stopCenter.lat;
    var lat2 = clusterCenter.lat;
    var lon1 = stopCenter.lon;
    var lon2 = clusterCenter.lon;
    var x1 = lat2 - lat1;
    var x2 = lon2 - lon1;
    var dLat = toRadians(x1);
    var dLon = toRadians(x2);
    var R = 3958.756; // miles
    var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
                  Math.cos(toRadians(lat1)) * Math.cos(toRadians(lat2)) *
                  Math.sin(dLon/2) * Math.sin(dLon/2);
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
    var d = R * c;
    return d;
  }


function toRadians(number){
  var inRadian = number * Math.PI / 180;
//  console.log('number->', number, 'inRadian->', inRadian);
  return inRadian;
}


     function findClosestStop(stops, cluster){
       //set new indeces
      var startIndex = 0;
      var endIndex = stops.length-1;

      //set new stop objects
      var firstStop = stops[startIndex];
      var lastStop = stops[endIndex];
      var closestStop;
      var returnIndex = 0;

      //dS: distance between the first stop and the cluster Center
      //dE: distance between the last stop and the cluster center
      var dS = findDistance(firstStop, cluster);
      var dE = findDistance(lastStop, cluster);
      if (dS > dE){
        startIndex = startIndex+endIndex / 2;
        returnIndex = 1;
      }
      if(dE > dS){
        endIndex = startIndex+endIndex / 2;
        returnIndex = 0;
      }

      if(stops.length > 2){
        stops = stops.slice(startIndex,(endIndex+1));
        return findClosestStop(stops, cluster);
      }else if(stops.length === 2){
        return stops[returnIndex];
      }else{
        return stops[0];
      }
    }
distance.js

    ...

        var distance = new distance.Distance();

    ...
        function createGTFSCluster(name, lat, lng, walk, bike, map) {
            var deferred = $q.defer();

            var clusterCenter = new graph.Center(lat, lng, map);
            var cluster = new graph.NodeCluster(clusterCenter, walkRadius, bikeRadius);

            cluster.setName(name);

            getRoutesNearby(cluster.clusterCenter, cluster.bikeRadius)
                .then(function(results) {
                    // Set the cluster's nearby routes
                    var routes = results[0];
                    cluster.nearbyRoutes = routes;
                    angular.forEach(routes, function(route, index){
                        getStopsByRoute(agency_key,route.route_id, 1).then(function(json){
                                            console.log(index, '->', route.route_id);
                            var stops = json[0];
                            var closestStop = distance.getClosestStop(stops, cluster);
                            cluster.setNodes(closestStop, route);
                        })
                    });
                        // Set the cluster's nodes to the stops found
                        deferred.resolve(cluster);
                });

            return deferred.promise;
        }
    ...


    // Retrieves the routes near a certain point on the map
        //
        // Input: cluster - A node cluster on the map we are finding routes for
        // Output: A promise whose results are the nearby route IDs
        function getRoutesNearby(center, radius) {
            var deferred = $q.defer();

            // Query the GTFS service for nearby routes and draw them
            gtfs.getRoutesByLocation(agency_key, center.lat, center.lon, radius)
                .then(function(json) {
                    //Get all route objects not only IDs
                    var routes = [];
                    for(index in json){
                        routes.push(json[index]);
                    }

                    // We got the routes, resolve
                    deferred.resolve(routes);
                });

            return deferred.promise;
        }
...

    function getStopsByRoute(agency_key, route_id, direction_id){
        var deferred = $q.defer();
        gtfs.getStopsByRoute(agency_key, route_id, direction_id)
            .then(function(json){ //all stops on the route in one direction
                var stopsArr =[];
                stopsArr.push(json.data[0].stops);
                deferred.resolve(stopsArr);
            });
            return deferred.promise;
    }
    Distance.prototype.getClosestStop = function (stops, cluster){
      var closestStop = findClosestStop(stops, cluster);
      return closestStop;
    }

  function findDistance(stopObj, clusterObj){

    var stopCenter = {
      lat:stopObj.stop_lat,
      lon:stopObj.stop_lon
    };
    var clusterCenter = clusterObj.clusterCenter;

    var lat1 = stopCenter.lat;
    var lat2 = clusterCenter.lat;
    var lon1 = stopCenter.lon;
    var lon2 = clusterCenter.lon;
    var x1 = lat2 - lat1;
    var x2 = lon2 - lon1;
    var dLat = toRadians(x1);
    var dLon = toRadians(x2);
    var R = 3958.756; // miles
    var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
                  Math.cos(toRadians(lat1)) * Math.cos(toRadians(lat2)) *
                  Math.sin(dLon/2) * Math.sin(dLon/2);
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
    var d = R * c;
    return d;
  }


function toRadians(number){
  var inRadian = number * Math.PI / 180;
//  console.log('number->', number, 'inRadian->', inRadian);
  return inRadian;
}


     function findClosestStop(stops, cluster){
       //set new indeces
      var startIndex = 0;
      var endIndex = stops.length-1;

      //set new stop objects
      var firstStop = stops[startIndex];
      var lastStop = stops[endIndex];
      var closestStop;
      var returnIndex = 0;

      //dS: distance between the first stop and the cluster Center
      //dE: distance between the last stop and the cluster center
      var dS = findDistance(firstStop, cluster);
      var dE = findDistance(lastStop, cluster);
      if (dS > dE){
        startIndex = startIndex+endIndex / 2;
        returnIndex = 1;
      }
      if(dE > dS){
        endIndex = startIndex+endIndex / 2;
        returnIndex = 0;
      }

      if(stops.length > 2){
        stops = stops.slice(startIndex,(endIndex+1));
        return findClosestStop(stops, cluster);
      }else if(stops.length === 2){
        return stops[returnIndex];
      }else{
        return stops[0];
      }
    }

你在哪里浪费时间

我建议你用一些

console.time(timerName);
我也不知道你在哪里浪费时间。如果你确切地知道你在哪里丢失了,分析就会容易得多

105组数据对于客户端应用程序来说应该没有问题

(function monitorDigestCycle(angular) {
  var injector = angular.element(document.body).injector();
  if (!injector) {
    throw new Error('Missing Angular injector on the document body');
  }
  var $rootScope = injector.get('$rootScope');
  function dummy() {
    console.count('digest cycle');
  }
  window.stopWatching = $rootScope.$watch(dummy);
  console.log('run window.stopWatching() to stop watching the digest cycle');
}(window.angular));
现在我建议您在控制台中运行这两个代码段

这个片段计算你的角度摘要。只需将其放入控制台,然后使用应用程序即可

(function monitorDigestCycle(angular) {
  var injector = angular.element(document.body).injector();
  if (!injector) {
    throw new Error('Missing Angular injector on the document body');
  }
  var $rootScope = injector.get('$rootScope');
  function dummy() {
    console.count('digest cycle');
  }
  window.stopWatching = $rootScope.$watch(dummy);
  console.log('run window.stopWatching() to stop watching the digest cycle');
}(window.angular));
或者这个片段。它包装一个函数(您需要调整代码段以供自己使用),并记录函数调用的chrome分析器。这使得分析变得容易

(function profileScopeMethod() {
  var selector = 'find';
  var methodName = 'find';
  var name = selector + ':' + methodName;

  /* global angular */
  var el = angular.element(document.getElementById(selector));
  var scope = el.scope() || el.isolateScope();
  console.assert(scope, 'cannot find scope from ' + name);

  var fn = scope[methodName];
  console.assert(typeof fn === 'function', 'missing ' + methodName);
  var $timeout = el.injector().get('$timeout');
  var $q = el.injector().get('$q');

  scope[methodName] = function () {
    console.profile(name);
    console.time(name);

    // method can return a value or a promise
    var returned = fn();
    $q.when(returned).finally(function finishedMethod() {
      console.timeStamp('finished', methodName);

      $timeout(function afterDOMUpdate() {
        console.timeStamp('dom updated after', methodName);
        console.timeEnd(name);
        console.profileEnd();
        scope[methodName] = fn;
        console.log('restored', name);
      }, 0);
    });
  };
  console.log('wrapped', name, 'for measurements');
}());
在这里,您可以找到更多用于分析角度应用程序的代码片段

https://github.com/bahmutov/code-snippets

服务器端的计算速度比客户端快得多。不过,我还是不明白为什么需要4秒钟,你的n是多少,它能有多大?此外,虽然findClosestStop确实以日志n步骤运行,但我们不知道FindInstance是什么doing@juvian,n是路线上的公共汽车站数。根据我的经验,n永远不会超过105。在半径为0.5或1英里(最大)的区域内,路线的最大数量不超过10条。所以它应该是10*lg(105)。我更新了distance.js以包含findInstance方法。我只要4秒钟就可以了,但这需要更长的时间。我也不明白为什么要花这么长的时间,这就是我想知道的。你应该尝试使用chrome分析来检查哪个部分需要花很长时间来计算:@juvian,谢谢你的建议。我花了几个小时才明白如何使用开发人员工具。我最终发现我的计算大约需要50毫秒,但服务器响应平均需要4秒钟。当我查看源代码时,我明白了原因。再次感谢!伟大的我自己从未使用过它,但我知道它是一个很好的工具:)。是的,如果105*log(105)用了4秒的时间,那就大错特错了:)罗宾,非常感谢你的回答。这些对我来说都是全新的,需要一些时间。一旦我对你们的问题有了答案并理解了你们发送的信息片段,我会尽快给你们回信。我目前正在研究如何使用Chrome配置文件,因为我以前从未使用过这个工具。Robin,谢谢你的建议。通过使用chrome开发者工具,我终于发现性能问题不在我的计算中,而是在服务器端。我在控制台中运行了第一个代码段。它没有抛出任何错误。但我也不明白这对我有什么帮助。我想利用你的答案。为了更好地理解这些代码片段,我应该研究什么呢?我在console发布的第一个代码片段记录了您的角度摘要。比因说我们需要再深入一点。您对范围所做的每一个更改都会发布一个角度核心的摘要循环。这里可以找到一个很好的例子:。第二个片段是包装一个angular函数,这样一旦调用它,它就会启动一个chrome profiler,一旦函数调用完成,它就会停止配置文件。这将帮助您对函数进行更深入的分析。Chromes开发工具也在javascript中标记“昂贵”的东西(也在视频中解释)。