Express / Node.js:包含外部API查询结果; 加上故障排除路线

编辑:我仔细审查,并尝试从以下SOpost,这是非常丰富的解决scheme,但不幸的是没有能够设法使新的信息在我的情况下工作。

  • 什么是JSONP?
  • 与jQuery的jsonp
  • 与JSONP使用.ajax()的基本示例?
  • 使用jQuery创build跨域ajax JSONP请求

嗨! 我第一次尝试在Node.js&Express / MEAN堆栈应用程序中使用来自外部API(Google Books API – https://developers.google.com/books/docs/v1/using )的数据。 我正在使用google-books-search npm软件包( https://www.npmjs.com/package/google-books-search ) – 在这个时候,我不确定这是否让我更容易或更困难。

我花了整个周末的研究,试图解决我的问题。 我已经阅读了很多关于JSONP,AJAX等等的很酷的东西,但是担心我正在调查那些超出我当前理解能力的材料。 我希望能够在兔子洞进一步下降之前获得基本的工作。

这里是问题:

  1. 我的一半路线工作在浏览器和/或curl,但其他人不。
  2. 我能够从控制台中的外部API访问JSON查询结果,但无法操纵这些数据在我的HTML视图中显示。 我已经阅读了很多关于使用JSONP,但还没有能够使其工作。

以下是我想要的路线的解释:

  • app.get('/') – root – WORKS

  • app.get('/ authorsearch /:author') – 从Google Books API检索查询结果 – CAN从API中显示查询结果数据

  • app.get('/ titlesearch /:title') – 从Google Books API检索查询结果 – CAN从API中显示查询结果数据

  • app.post('/ books') – 将图书保存到数据库 – NOT THERE YET(因为我一直无法从API获取查询结果)

  • app.get('/ books /:id') – 从数据库中检索特定的书 – WORKS(当前显示空数组)

  • app.post('/ user') – 创build一个新用户并保存到数据库 – 不工作

  • app.post('/ login') – 现有的用户login – 不起作用
  • app.get('/ user /:id') – 从数据库检索用户的详细信息 – 不工作
  • app.put('/ user /:id') – 更新数据库中的用户详细信息 – WORKS
  • app.delete('/ user /:id') – 从数据库中删除用户帐户 – WORKS

我的目标是让用户能够按标题或作者search书籍。 注册/login的用户将能够将选定的书籍保存为collections夹,并在以后的会话中访问他们的书籍列表。

SERVER.JS

// DEPENDENCIES var express = require('express'), mongoose = require('mongoose'), bodyParser = require('body-parser'), md5 = require('md5'), cookieParser = require('cookie-parser'), morgan = require('morgan'), books = require('google-books-search'); var port = process.env.PORT || 3000; var app = express(); // MIDDLEWARE app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.json()); app.use(express.static('public')); app.use(cookieParser()); // DATABASE mongoose.connect('mongodb://localhost/google_books_app_db'); // MODELS var User = require('./models/user'); var Book = require('./models/book'); // LISTENER app.listen(port); console.log("server working on port " + port); // ======= // ======= // ROUTES // ======= // ======= // ===== // Root // ===== // root - WORKS app.get('/', function(req, res) { // res.render("index"); console.log("root working"); }); // =============================================== // Search routes - from Google Books API's server // =============================================== // GET books by search of author name - WORKS app.get('/authorsearch/:name', function(req, browserResponse) { //browserResponse.send("bannana"); return; //console.log( browserResponse.send ); var author = req.params.name; books.search("inauthor=" + author, function(err, bookSearchResponse) { if ( ! err ) { browserResponse.send( bookSearchResponse ); //console.log(res); // $('body').append(res); // res.json(req.body); } else { console.log(err); }; // end if/else }); // end search }); // end get books by author // GET books by search of title - WORKS app.get('/titlesearch/:title', function(req, browserResponse) { var title = req.params.title; books.search("intitle=" + title, function(err, bookSearchResponse) { if ( ! err ) { browserResponse.send( bookSearchResponse ); // $('#results-container').append(res); // res.json(req.body); } else { console.log(err); }; // end if/else }); // end search }); // end get books by title // ============================ // Book routes - from local db // ============================ // GET books - WORKS (shows empty array) app.get('/books/:id', function(req, res) { Book.find({ 'user': req.params.id }).exec(function(err, books) { console.log("getting books"); res.send(books); }); }); // ============ // User routes // ============ // CREATE new user sign-up app.post('/user', function(req, res) { var password_hash = md5(req.body.password); var user = new User({ username: req.body.username, password_hash: password_hash }); user.save(function(err) { if (err) { console.log(err); res.statusCode = 503; } else { console.log(user.username + " created server side"); res.cookie("loggedInUserId", user.id) res.send(user); }; //end if/else }); // end save }); // end new sign-up // POST user log-in app.post('/login', function(req, res) { var req_username = req.body.username; var req_password = req.body.password; req_password_hash = md5(req_password); User.findOne({ 'username' : req_username }).exec(function(err, user) { if (user != null && req_password_hash == user.password_hash) { res.cookie("loggedInUserId", user.id); res.send(user); } else { console.log("Error, try again"); }; // end if/else }); // end findOne }); // end log-in // GET user by ID app.get('/user/:id', function(req, res) { console.log("Find one user"); User.findById(req.params.id).then(function(user) { res.send(user); }); // end findById }); // end get user // UPDATE edit user account - WORKS app.put('/user/:id', function(req, res) { console.log("User edit request"); User.findOneAndUpdate( { _id: req.params.id }, req.body, function(err, user) { console.log("User updated"); res.send(user); }); // end findOneAndUpdate }); // end edit user // DELETE user account - WORKS app.delete('/user/:id', function(req, res) { console.log("User delete request"); User.findOneAndRemove( { _id: req.params.id }, function(err) { res.clearCookie("loggedInUserId"); console.log("User cookie cleared"); res.send("User deleted"); }); // end findOneAndRemove }); // end delete user // END OF USER ROUTES // END OF ALL ROUTES 

APP.JS

 console.log("loaded"); $(document).ready(function() { console.log("document onload"); // ============= // CLICK EVENTS // ============= // search by author button $('#author-searchbtn').on('click', function() { // console.log("debugger hello"); var searchAuthor = $('#search-field').val(); searchByAuthor(searchAuthor); }); // end onclick // search by title button $('#title-searchbtn').on('click', function() { var searchTitle = $('#search-field').val(); searchByTitle(searchTitle); }); // end onclick // new user sign-up button $('#register-btn').click(function() { console.log("Clicked register"); newUser(); }); // user log-in button $('#login-btn').click(function() { console.log("Clicked login"); loginPost(); }) // user log-out button $('#logout-btn').click(function() { Cookies.remove('loggedInUserId'); console.log("User cookie deleted; user logged out"); }); // ================= // SEARCH FUNCTIONS // ================= // WORKS var searchByAuthor = function(searchAuthor) { console.log("about to make ajax request"); $.ajax({ url: '/authorsearch/' + searchAuthor // url: 'https://www.googleapis.com/books/v1/volumes?inauthor=' + searchAuthor }).done(function(res) { console.log("ajax author response recieved"); console.log(res); console.log("===========SEARCHED BY AUTHOR==========="); }) // end Ajax call console.log( "ajax author request made"); //handleResponse(res); }; // end searchByAuthor // WORKS var searchByTitle = function(searchTitle) { console.log("about to make ajax request"); $.ajax({ url: '/titlesearch/' + searchTitle }).done(function(data) { console.log("ajax title response recieved"); console.log(data); // $('#results-container').html(data); console.log("===========SEARCHED BY TITLE==========="); for (var i = 0; i < data.items.length; i++) { var item = data.items[i]; document.getElementById("results-container").innerHTML += "<br>" + item.volumeInfo.authors; console.log(item.volumeInfo.authors); }; console.log(data.items[3]); }); // end Ajax call console.log( "ajax title request made"); // handleResponse(data); }; // end searchByTitle // HAVEN'T GOTTEN HERE YET var handleResponse = function(res) { for (var i=0; i < res.items.length; i++) { var item = resp.items[i]; document.getElementById('#results-container').innerHTML; }; // end for loop }; // end handleResponse // HAVEN'T GOTTEN HERE YET - NOT SURE IF IT WILL BE NEEDED var displayBooks = function(res) { // displayBooks(); }; // end displayBooks // =============== // USER FUNCTIONS // =============== var setUp = function() { console.log("setting up"); if (Cookies.get("loggedInUserId") != undefined) { console.log("already logged in"); }; }; var newUser = function() { user = { username: $('#username').val(), password: $('#password').val(), }; console.log(user); $.ajax({ url: '/user', method: 'POST', dataType: 'json', data: user }).done(function(data) { user = Cookies.get('loggedInUserId'); }); // end ajax request }; // end newUser var loginPost = function() { user = { username: $('#username').val(), password: $('#password').val(), }; $.ajax({ url: '/login', method: 'POST', dataType:'json', data: user }).done(function(data) { console.log("submitted login info"); }).fail(function() { console.log("login failed"); }); // end ajax request }; //end userLogin }); // end document ready 

INDEX.HTML – 请注意,模板没有启动和运行,所以我只有一个非常基本的视图(search栏和button,用户registry单,用户login表单,注销button)。

 <html> <head> <script type="text/javascript" src="https://code.jquery.com/jquery-2.1.4.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/js-cookie/2.0.4/js.cookie.js"></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.4/handlebars.js"></script> <link rel="stylesheet" type="text/css" href="css/styles.css"> <title>Google Books App</title> </head> <body> <h1>Discover Literature</h1> <div id="search-container"> <p>Find something you'll love.</p> <input type="text" id="search-field"> <button id="author-searchbtn">Search by Author</button> <button id="title-searchbtn">Search by Title</button> </div> <div id="results-container"> </div> <br><br> <!-- TEMP SIGN-UP --> <div id="signup-container" data-id="{{_id}}"> <b>Sign up</b> <br> <label for="username">Username</label><br/> <input type="text" id="username" placeholder="username"/><br> <label for="password">Password</label><br/> <input type="text" id="password" placeholder="password"/><br> <button id="register-btn" data-id="{{_id}}">Register!</button> </div> <br><br> <!--TEMP LOG-IN --> <div id="login-container" data-id="{{_id}}"> <b>Log in</b> <br> <label for="username">Username</label><br/> <input type="text" id="username" placeholder="username"/><br> <label for="password">Password</label><br/> <input type="text" id="password" placeholder="password"/><br> <button id="login-btn" data-id="{{_id}}">Login!</button> </div> <br><br> <!-- TEMP LOG-OUT BUTTON --> <b>Log out</b> <br> <button id="logout-btn">Log out</button> <!-- ============== TEMPLATES ============== --> <!-- add sign-up and log-in templates --> <!-- edit user account --> <template id="edit-user-template"> <div id="edit-user-container" data-id="{{_id}}"> <button id="account-delete-button">Delete account</button><br> </div> </template> <!-- delete user account --> <template id="delete-user-template"> <div id="delete-user-container" data-id="{{_id}}"> Please confirm. <button id="delete-user-confirm-button" data-id="{{_id}}">Delete my account</button> </div> </template> <!-- ============== END TEMPLATES ============== --> <script src="js/app.js"></script> </body> </html> 

谢谢你的见解!