简单的Node.JS REST API调用

亚历克斯·怀

我有一个简单的应用程序,需要REST API调用才能执行CRUD(创建,读取,更新,删除)。但是,我似乎无法使REST API正常工作。

当它执行put操作时,我得到

“ api.js:81未捕获(承诺)SyntaxError:在callAPI(api.js:81)上意外的JSON输入结尾”

我正在使用Api.js检查API调用。

api-photos.js

//photos.js
var express = require('express');
var router = express.Router();
var multer = require('multer');
var photoController = require('../../controllers/photoController');
var upload = multer({
  storage: photoController.storage,
  fileFilter: photoController.imageFilter
});

//import PhotoService
const PhotoService = photoController.PhotoService;

router.use((req, res, next)=>{
  //set mime type for all request and origin
  res.set({
    'Access-Control-Allow-Origin':'*',
    'Access-Control-Allow-Methods':'GET,PUT,POST,DELETE,OPTIONS',
    "Access-Control-Allow-Headers":"Content-Type, Access-Control-Allow-Headers",
    'Content-type':'applicaion/json'
  });
  if(req.method == 'OPTIONS'){
    return res.status(200).end();
  }
  next();
})
// photos - list
router.get('/', (req, res, next)=>{
  PhotoService.list()
  //returns promise - argument passed photos
    .then((photos)=>{
      console.log(`API: Found images: ${photos}`);
      res.status(200);
      //set content type header to application/json - set correct mime type
      res.send(JSON.stringify(photos));
    });
})

// photos/:photoid - find
router.get('/:photoid', (req, res, next)=>{
  PhotoService.read(req.params.photoid)
  //returns promise - argument passed photos
    .then((photo)=>{
      console.log(`API: Found images: ${photo}`);
      res.status(200);
      //set content type header to application/json - set correct mime type
      res.send(JSON.stringify(photo));
    }).catch((err)=>{
  });
});

// /photos POST create

router.post('/', upload.single('image'), async (req, res, next)=>{
  var path = "/static/img/" + req.file.filename;

  var photo = {
    originalname: req.file.originalname,
    mimetype: req.file.mimetype,
    imageurl: path,
    title: req.body.title,
    filename: req.file.filename,
    description: req.body.description,
    size: req.file.size / 1024 | 0
  }
//calling on photo service to return json object
  try{
    const photoSave = await PhotoService.create(photo);
    res.status(201);
    res.send(JSON.stringify(photoSave));
  }catch(err){
    console.log(err);
    throw new Error("PhotoSaveError", photo);
  }

});

// /photos/photoid: PUT - update
  router.put('/:photoid', (req, res, next)=>{
    console.log(`putting ${req.params.photoid}`);
    let putdata = req.body;
    PhotoService.update(req.params.photoid, putdata)
       console.log()
      .then((updatePhoto)=>{
        res.status(200);
        res.send(JSON.stringify(updatedPhoto));
      }).catch((err)=> {
        res.status(404);
        res.end();
    });
  });

// /photos/photoid: DELETE - delete
  router.delete('/:photoid', (req, res, next)=>{
    PhotoService.delete(req.params.photoid)
      .then((photo) => {
        console.log(`Found images: $(photo)`);
        res.status(200);
        res.send(JSON.stringify(photo));
      }).catch((err)=> {
        res.status(404);
        res.end();
      });;
  });



module.exports = router;

photo.js

//photos.js
var express = require('express');
var router = express.Router();
var app = express();
var multer = require('multer');
var photoController = require('../controllers/photoController');
var flash = require('express-flash');

//create upload object- intialize
var upload = multer({
  storage: photoController.storage,
  fileFilter: photoController.imageFilter
});

//Photo model import is required
var Photo = require('../models/photoModel');
const PhotoService = photoController.PhotoService

//flash messaging
router.use(flash());

//LIST - Get request to search database for our photos
router.get('/', (req, res, next)=>{
//search the DB for the photos
  PhotoService.list()
    .then((photos)=>{
//call photos view
      res.render('photos', {
        photos : photos,
        flashMsg: req.flash("fileUploadError")
    });
  })
  .catch((err)=>{
    if (err) {
      res.end("ERROR!");
    }
  });
});

//FIND - route for getting photo Details with form for editing
router.get('/:photoid', (req, res, next)=>{
  console.log("finding "+req.params.photoid);
  PhotoService.read({'_id': req.params.photoid})
//return promoise then handle it to render photo
    .then((photo)=>{
      res.render('updatePhoto', {
        photo: photo,
        flashMsg: req.flash("photoFindError")
      });
    }).catch((err)=>{
      if (err) console.log(err);
    });
});

//DELETE - route for deleting the photos
router.delete('/delete/:photoid', function(req, res){
  PhotoService.delete({'_id': req.params.photoid})
  .then((photos) => {
      res.redirect('/photos');
  });
});

//UPDATE - route for posting newly updated details
router.post('/:photoid', (req, res, next)=>{
  PhotoService.update({'_id': req.params.photoid})
//return promoise then set photo data details
    .then((photo)=>{
      var data = {
          title: req.body.title,
          description: req.body.description
          }
//set the data, save the photo details and redirect to photo list
      photo.set(data);
      photo.save().then(()=>{
        res.redirect('/photos');
      });
    })
    .catch((err)=>{
      if (err) console.log(err);
  });
});

//CREATE - post fields to the server and save them
router.post('/', upload.single('image'), (req, res, next)=>{
  var path = "/static/img/" + req.file.filename;
  var photo = {
    originalname: req.file.originalname,
    mimetype: req.file.mimetype,
    imageurl: path,
    title: req.body.title,
    filename: req.file.filename,
    description: req.body.description,
    size: req.file.size / 1024 | 0
  }
//Saving photo to DB
  var photo = new Photo(photo);
  photo.save()
    .then(()=>{
      //redirect after save, if succesfull
      res.redirect('/photos');
    })
    //Catch error  logs error
    .catch((err)=>{
      if (err){
        console.log(err);
        throw new Error("PhotoSaveError", photo);
      }
    });
});

//function will get called if above gets unhandled error - flash to display image and redirect
router.use(function(err, req, res, next){
  console.error(err.stack);
  if (err.message == "OnlyImageFilesAllowed"){
      req.flash('fileUploadError', "Please select an image file with jpg, png, or gif")
      res.redirect('/photos');
//2nd condition error if there was a problem saving
  } else if (err.message == "PhotoSaveError"){
    req.flash('photoSaveError', "There was a problem saving the photo")
    res.redirect('/photos');
  } else{
    next(err);
  }
});

//export the module
module.exports = router;

api.js

// wrap in IIFE to control scope
(function(){

   const baseURL = 'http://localhost:8080';

   function testAPIs(){
    // test list first
    var testId = '';
    var testJSON = {};

    // list
    callAPI('GET', '/api/photos', null, null)
      .then((list)=>{
        console.log('\n\n***************************\nlist results:');
        console.log(list);
        testId = list[0]._id;

        // create
        let input = document.querySelector('input[type="file"]')
        let data = new FormData()
        data.append('image', input.files[0]);
        data.append('title', 'My API Test Title');
        data.append('description','This is an AJAX API test');
        callAPI('POST', '/api/photos', null, data)
          .then((photo)=>{
            photoId = photo._id;
            savedPhoto = photo;  // keep a handle to the created photo object
            console.log('\n\n***************************\ncreate results:');
            console.log(photo);

            // find
            callAPI('GET','/api/photos/'+photoId, null, null)
              .then((photo)=>{
                console.log('\n\n***************************\nfind results:');
                console.log(photo);

                // update
                testJSON.description += ' appended by the AJAX API ';
                callAPI('PUT','/api/photos/'+photoId, null, savedPhoto)
                  .then((photo)=>{
                    console.log('\n\n***************************\nupdate results:');
                    console.log(photo);

                    //delete
                    callAPI('DELETE', '/api/photos/'+photoId, null, null)
                     .then((result)=>{
                       console.log('\n\n***************************\ndelete result:');
                       console.log(result);
                     })
                });
            });
        });
    })
    .catch((err)=>{
      console.error(err);
    });
}


  async function callAPI(method, uri, params, body){
    jsonMimeType = {
      'Content-type':'application/json'
    }
    try{
      /*  Set up our fetch.
       *   'body' to be included only when method is POST
       *   If 'PUT', we need to be sure the mimetype is set to json
       *      (so bodyparser.json() will deal with it) and the body
       *      will need to be stringified.
       *   '...' syntax is the ES6 spread operator.
       *      It assigns new properties to an object, and in this case
       *      lets us use a conditional to create, or not create, a property
       *      on the object. (an empty 'body' property will cause an error
       *      on a GET request!)
       */
      var response = await fetch(baseURL + uri, {
        method: method, // GET, POST, PUT, DELETE, etc.
        ...(method=='POST' ? {body: body} : {}),
        ...(method=='PUT' ?  {headers: jsonMimeType, body:JSON.stringify(body)} : {})
      });
      return response.json(); // parses response to JSON
    }catch(err){
      console.error(err);
      return "{'status':'error'}";
    }
  }

  // Calls our test function when we click the button
  //  afer validating that there's a file selected.
  document.querySelector('#testme').addEventListener("click", ()=>{
    let input = document.querySelector('input[type="file"]')
    if (input.value){
      testAPIs();
    }else{
      alert("please select an image file first");
    }
  });
})();
催化剂

这是一个更新的PUT处理程序,应该停止抛出“ ...的未定义.then”,请注意也updatePhoto需要重命名updatedPhoto为。

router.put('/:photoid', (req, res, next) => {
  console.log(`putting ${req.params.photoid}`);
  let putdata = req.body;
  PhotoService.update(req.params.photoid, putdata).then((updatedPhoto) => {
      res.status(200);
      res.send(JSON.stringify(updatedPhoto));
    }).catch((err) => {
      res.status(404);
      res.end();
    });
});

如果使用的是节点8+,则可以使用async / await。它简化了代码并使问题更容易发现:

router.put('/:photoid', async (req, res, next) => {
  try {
    console.log(`putting ${req.params.photoid}`);
    let putdata = req.body;
    const updatedPhoto = await PhotoService.update(req.params.photoid, putdata);
    res.status(200);
    res.send(JSON.stringify(updatedPhoto));
  } catch (e) {
    res.status(404);
    res.end();
  }
});

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

node.js 中的 Rest api 调用问题

来自分类Dev

Node.js Twilio 使用 REST API 进行调用

来自分类Javascript

使用Node.js和Express进行简单的API调用

来自分类Dev

反应JS Rest Api调用

来自分类Dev

REST API node.js

来自分类Dev

调用Rest API时,Node.js Discord机器人消息为空

来自分类Dev

使用setInterval调用rest api并在node.js中承诺

来自分类Dev

使用Node.js Express的Rest API

来自分类Dev

使用 Node Js 和 express 调用来自 rest api 的 post 请求时出错。请求数据变空

来自分类Dev

对JBPM REST API进行简单调用时出现NotFoundException

来自分类Dev

带有Node.js Rest API的React.js

来自分类Dev

在 Node js 中 Rest Api 请求(curl 到 Node.js,python 到 Node.js)

来自分类Dev

在 React JS web 应用中使用 Axios 调用 Rest Api

来自分类Dev

如何通过Vue JS调用REST API服务

来自分类Dev

使用骨干.js禁用OPTIONS标头以调用REST API

来自分类Dev

使用Angular JS,CORS调用Symfony 2 Rest API

来自分类Dev

通过节点js调用jasper report rest api

来自分类Javascript

使用Node.js调用JSON API

来自分类Dev

在 node.js 中调用restful api

来自分类Dev

Node.js中的同步api调用

来自分类Dev

API调用上的Node.js循环

来自分类Dev

gatsby-node.js 多个 api 调用

来自分类Dev

在使用node.js中的REST API时请求参数

来自分类Dev

如何为Node.js REST API正确配置Nginx?

来自分类Dev

Node.js REST API版本控制正确吗?

来自分类Dev

Node.js中Rest API的Forever Forever模块

来自分类Javascript

保护我的Node.js应用程序的REST API?

来自分类Dev

Node js App与Power Bi Rest Api的集成

来自分类Dev

如何使用node.js实现安全的REST API