Angular js factory不会返回404错误

时间:2016-03-22 08:25:12

标签: javascript jquery angularjs

我正在构建一个小项目,让用户可以保留艺术家和专辑的列表,我需要一个可以匹配此类内容的预先输入/自动完成。我从last.fm typeahead中获取灵感。

我的HTML代码:

<!DOCTYPE html>
<html class="js flexbox flexboxlegacy canvas canvastext webgl no-touch geolocation postmessage websqldatabase indexeddb hashchange history draganddrop websockets rgba hsla multiplebgs backgroundsize borderimage borderradius boxshadow textshadow opacity cssanimations csscolumns cssgradients cssreflections csstransforms csstransforms3d csstransitions fontface generatedcontent video audio localstorage sessionstorage webworkers applicationcache svg inlinesvg smil svgclippaths ng-scope" ng-app="ymusica"><!--<![endif]--><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <title>ymusica</title>
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width">

        <link rel="stylesheet" href="lib/css/bootstrap.css">
        <link rel="stylesheet" href="lib/css/main.css">
        <script src="lib/js/modernizr.js"></script>
    <style type="text/css">@charset "UTF-8";[ng\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\:form{display:block;}</style></head>
    <body>
        <!--[if lt IE 7]>
            <p class="chromeframe">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">activate Google Chrome Frame</a> to improve your experience.</p>
        <![endif]-->

        <div class="container">
             <div ng-controller="AlbumSearch" class="album-search text-center" ng-cloak>
                 <typeahead class="typeahead" items="music" term="term" search="searchMusic(term)" select="selectMusic(item)">
                     <div class="menu" ng-cloak>
                         <h3 ng-show="hasAlbums()">Albums</h3>
                         <ul>
                             <li typeahead-item="album" ng-repeat="album in albums" class="results">
                                 <img ng-src="{{imageSource(album)}}"><p class="name">{{album.name}}</p><p class="artist">{{album.artist}}</p>
                             </li>
                         </ul>
                         <h3 ng-show="hasArtists()">Artists</h3>
                         <ul>
                             <li typeahead-item="artist" ng-repeat="artist in artists" class="results">
                                 <img ng-src="{{imageSource(artist)}}"><p class="name">{{artist.name}}</p>
                             </li>
                         </ul>
                     </div>
                 </typeahead>
             </div>
         </div>

        <script src="lib/js/jquery.js"></script>
        <script src="lib/js/rx.js"></script>
        <script src="lib/js/rx.time.js"></script>
        <script src="lib/js/rx.coincidence.js"></script>
        <script src="lib/js/angular.js"></script>
        <script src="lib/js/module.js"></script>
        <script src="lib/js/ymusica.js"></script>
        <script src="lib/js/controller.js"></script>
        <script src="lib/js/service.js"></script>
        <script src="lib/js/typeahead.js"></script>
        <script src="lib/js/angular-resource.js"></script>
        <script src="lib/js/bootstrap.js"></script>


      </body>
</html>

我的控制器代码:

angular.module('ymusica').controller('AlbumSearch', ['$scope', 'Albums', 'Artists', '$q', function($scope, albums, artists, $q) {

$scope.albums = [];
$scope.artists = [];

var watchToObservable = function(scope, expression) {
    var observable = new Rx.Subject();

    scope.$watch(expression, observable.onNext.bind(observable));

    return observable;
}

var functionToObservable = function(scope, name) {

    var observable = new Rx.Subject();

    scope[name] = function(value) {
        observable.onNext(value);
    };

    return observable;
}

var terms = functionToObservable($scope, 'searchMusic');

terms.sample(250)
    .select(function(term) {
        var promise = $q.all([albums.query(term), artists.query(term)]);
        return Rx.promiseToObservable(promise)
    })
    .switchLatest()
    .select(function(promise) { return [promise[0].data.albums, promise[1].data.artists]; })
    .subscribe(function(result) {
        $scope.albums = result[0].slice(0, 5);
        $scope.artists = result[1].slice(0, 5);
        $scope.music = $scope.albums.concat($scope.artists);
    });

$scope.selectMusic = function(item) {
    console.log('music selected!', item);
    $scope.term = item.name;
};

$scope.imageSource = function(item) {
    return item.images['medium'];
};

$scope.hasAlbums = function() {
    return $scope.albums.length > 0;
};

$scope.hasArtists = function() {
    return $scope.artists.length > 0;
};

}]);

我的service.js代码:

angular.module('ymusica').factory('Albums', ['$http', function($http) {
return {
    query: function(term) {
        return $http.get('/api/album', { params: { q: term } });
    }
  };
}]);

angular.module('ymusica').factory('Artists', ['$http', function($http) {
return {
    query: function(term) {
        return $http.get('/api/artist', { params: { q:term } });
    }
  };
}]);

最后

我的typeahead.js代码(指令):

angular.module('ymusica').directive('typeahead', ["$timeout",  function($timeout) {
return {
    restrict: 'E',
    transclude: true,
    replace: true,
    template: '<div><form><input ng-model="term" ng-change="query()"  type="text" autocomplete="off" /></form><div ng-transclude></div></div>',
    scope: {
        search: "&",
        select: "&",
        items: "=",
        term: "="
    },
    controller: ["$scope", function($scope) {
        $scope.items = [];
        $scope.hide = false;

        this.activate = function(item) {
            $scope.active = item;
        };

        this.activateNextItem = function() {
            var index = $scope.items.indexOf($scope.active);
            this.activate($scope.items[(index + 1) % $scope.items.length]);
        };

        this.activatePreviousItem = function() {
            var index = $scope.items.indexOf($scope.active);
            this.activate($scope.items[index === 0 ? $scope.items.length - 1  : index - 1]);
        };

        this.isActive = function(item) {
            return $scope.active === item;
        };

        this.selectActive = function() {
            this.select($scope.active);
        };

        this.select = function(item) {
            $scope.hide = true;
            $scope.focused = true;
            $scope.select({item:item});
        };

        $scope.isVisible = function() {
            return !$scope.hide && ($scope.focused || $scope.mousedOver);
        };

        $scope.query = function() {
            $scope.hide = false;
            $scope.search({term:$scope.term});
        }
     }],

    link: function(scope, element, attrs, controller) {

        var $input = element.find('form > input');
        var $list = element.find('> div');

        $input.bind('focus', function() {
            scope.$apply(function() { scope.focused = true; });
        });

        $input.bind('blur', function() {
            scope.$apply(function() { scope.focused = false; });
        });

        $list.bind('mouseover', function() {
            scope.$apply(function() { scope.mousedOver = true; });
        });

        $list.bind('mouseleave', function() {
            scope.$apply(function() { scope.mousedOver = false; });
        });

        $input.bind('keyup', function(e) {
            if (e.keyCode === 9 || e.keyCode === 13) {
                scope.$apply(function() { controller.selectActive(); });
            }

            if (e.keyCode === 27) {
                scope.$apply(function() { scope.hide = true; });
            }
        });

        $input.bind('keydown', function(e) {
            if (e.keyCode === 9 || e.keyCode === 13 || e.keyCode === 27) {
                e.preventDefault();
            };

            if (e.keyCode === 40) {
                e.preventDefault();
                scope.$apply(function() { controller.activateNextItem(); });
            }

            if (e.keyCode === 38) {
                e.preventDefault();
                scope.$apply(function() { controller.activatePreviousItem();  });
            }
        });

        scope.$watch('items', function(items) {
            controller.activate(items.length ? items[0] : null);
        });

        scope.$watch('focused', function(focused) {
            if (focused) {
                $timeout(function() { $input.focus(); }, 0, false);
            }
        });

        scope.$watch('isVisible()', function(visible) {
            if (visible) {
                var pos = $input.position();
                var height = $input[0].offsetHeight;

                $list.css({
                    top: pos.top + height,
                    left: pos.left,
                    position: 'absolute',
                    display: 'block'
                });
            } else {
                $list.css('display', 'none');
            }
        });
    }
  };
 }]);

angular.module('ymusica').directive('typeaheadItem', function() {
return {
    require: '^typeahead',
    link: function(scope, element, attrs, controller) {

        var item = scope.$eval(attrs.typeaheadItem);

        scope.$watch(function() { return controller.isActive(item); }, function(active) {
            if (active) {
                element.addClass('active');
            } else {
                element.removeClass('active');
            }
        });

        element.bind('mouseenter', function(e) {
            scope.$apply(function() { controller.activate(item); });
        });

        element.bind('click', function(e) {
            scope.$apply(function() { controller.select(item); });
        });
    }
 };
});

我也在使用last.fm api。请帮我解决问题。在原始last.fm代码工作正常,但我的代码返回404错误,虽然使用相同的api路径。

1 个答案:

答案 0 :(得分:0)

您似乎正在尝试从您自己的域中获取URL /api/artist,而不是从Last.fm的服务器中获取:

return $http.get('/api/artist', { params: { q:term } })
<德尔> 我_think_它应该是: return $http.get('https://last.fm/api/artist', { params: { q:term }});

docs说:

  

API根网址位于http://ws.audioscrobbler.com/2.0/

此外,我没有看到使用/api/artist参数搜索q的终点,尽管他们确实有search endpoints