使用Ionic(AngularJS框架)与MongoDB建立连接

简述

使用Ionic进行开发时,我读取了一个假的Json文件并显示了其中的数据,但是我意识到必须正确地连接到数据库,于是我决定在本地搭建MongoDB并记录连接的过程。

另外,由于最终计划是将与AWS的DynamoDB连接的请求嵌入到Angular的Controller中,所以Node.js->MongoDB只是用于测试目的而构建。

前提 tí)

下面是开发环境。

    • OS: Mac OS X El Capitan

 

    • Angular: 1.X系

 

    • Cordova CLI: 6.0.0

 

    • Gulp version: CLI version 3.9.1

 

    • Ionic Version: 1.2.4

 

    • Ionic CLI Version: 1.7.14

 

    • Ionic App Lib Version: 0.7.0

 

    • Node Version: v5.5.0

 

    MongoDB shell version: 3.2.5

Angular是否可以与MongoDB一起使用?

最初我搜索了关于能否连接前端的Angular和Mongo的问题。根据J2EE的思路,我认为可以直接从Servlet(Web容器)连接到DAO层进行调查,但结果看起来确实有些困难(当然,在运行Ionic时使用的服务器似乎是Node.js,所以可能是可行的。但是,我对此的印象是由于有许多考虑事项而变得非常麻烦)

所以,我们转向了替代方案。

Ionic(Angular) -> Node -> MongoDB

Ionic(Angular)在Node上连接MongoDB。

我本能地尝试着在两者之间加入一个Node服务器进行通信,希望能成功。

var express = require('express'),
    mongodb = require('mongodb');

var app = express();
app.set('port', process.env.PORT || 3000);

// 私の環境ではMongoのポートである{ポート番号}=27017
// Nodeサーバのポート番号は3000としています
mongodb.MongoClient.connect("mongodb://localhost:{ポート番号}/{DB名称}", function(err, database) {
  tmp = database.collection("{コレクション名称}");
});

// Acquiring the list of goods we bought
app.get("/api/tmp", function(req, res) {
  tmp.find().toArray(function(err, items) {
    res.send(items);
  });
});

// サーバ起動
http.createServer(app).listen(app.get('port'), function() {
  console.log('Node.js with Express server listening on port ' + app.get('port'));
});

执行app.js。

$ node app.js
Node.js使用Express服务器在3000端口监听。

由于内部结构简单,服务器可以轻松启动。

执行离子端。

接下来,我们将按照以下方式对ionic进行编码。

    var url = 'http://localhost:3000/api/tmp';
    $scope.tmplist = [];
    $http.get(url).success(function(data, status) {
      // set json data acquired from DB
      console.info(status, data);
      $scope.tmpList = data;
    }).error(function(data, status) {
      // if cannot get data from DB, set local json data to goodsList
      console.error(status, data);
    });

我也会启动Ionic。然后在隐私模式下启动Chrome,并同时启动开发人员工具进行确认。

使用Ionic命令在iOS设备上进行本地测试—>ionic 本地测试 iOS 设备

从浏览器确认!

(浏览器搜索)http://localhost:8100/ -> (浏览器搜索)http://localhost:8100/

当时出现错误,无法正常运行。。。查看谷歌浏览器的控制台后发现以下错误。

XMLHttpRequest无法加载http://localhost:3000/api/tmp。请求的资源未包含’Access-Control-Allow-Origin’标头。因此,不允许访问来自http://localhost:8100的请求源。

跨域资源共享(CORS)吗?确实,当使用MEAN堆栈构建应用程序时,通常不需要担心Node和Angular是否在同一域上。因为我使用Angular进行编写,所以没有意识到这一点,但是由于Node服务器和ionic服务器位于不同域上,所以需要考虑这个问题。

(*1) CORS:跨源资源共享的缩写。它是浏览器从加载HTML的服务器之外的服务器获取数据的机制。一般的浏览器已经实现了通过XSS防止跨域通信的机制。

用JSONP来处理一下

可以添加一个不使用CORS的标头,但是由于不同域的JSON数据获取通常使用JSONP请求,我们可以尝试将GET请求改为JSONP请求进行提交。

以下是一个本地化的中文翻译(仅提供一个选项):

<参考>
https://docs.angularjs.org/api/ng/service/$http#jsonp
http://qiita.com/izumin5210/items/e6e529d61c4d246f87fb

以上链接提供了有关AngularJS中的”$http”服务和”jsonp”方法的相关信息。

    var url = 'http://localhost:3000/api/tmp?callback=JSON_CALLBACK';
    $scope.tmplist = [];
    $http.jsonp(url).success(function(data, status) {
      // set json data acquired from DB
      console.info(status, data);
      $scope.tmpList = data;
    }).error(function(data, status) {
      // if cannot get data from DB, set local json data to goodsList
      console.error(status, data);
    });

再次使用ionic从Chrome访问!!…嗯?不起作用…
对了,还是有CORS问题。
*即使从浏览器访问目标url1(http://localhost:3000/api/tmp),可以正确获取JSON格式的数据。

尽管我尝试过各种方法来研究JSONP的用法,并在app.js中明确设置返回JSON的形式,但没有任何变化,所以我决定转到下一个策略。

在HTTP响应中加入Access-Control标头

试着根据《在Express上使用CORS》这篇文章中的参考方式进行集成。

var express = require('express'),
    mongodb = require('mongodb');

var app = express();
app.set('port', process.env.PORT || 3000);
app.use(function(req, res) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
});

・・・省略・・・

// Acquiring the list of goods we bought
app.get("/api/tmp", function(req, res) {
  tmp.find().toArray(function(err, items) {
    res.send(items);
  });
});

提升节点服务器,执行ionic命令并确认结果,CORS问题已经消失了,但是仍然没有收到任何HTTP响应,无法进行屏幕渲染。根据下面的指示,尝试将其明确地嵌入头部,问题得到了解决。

var express = require('express'),
    mongodb = require('mongodb');

var app = express();
app.set('port', process.env.PORT || 3000);

・・・省略・・・

// Acquiring the list of goods we bought
app.get("/api/tmp", function(req, res) {
  tmp.find().toArray(function(err, items) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    res.send(items);
  });
});

因为这种方法需要在每个请求中都加入CORS绕过头部,所以我觉得不是很好,但是因为其他方法都不起作用,所以只能放弃了。

目前,我成功地使用Ionic实现了与MongoDB的通信,感到非常满意。
此外,当使用DynamoDB时,请将http.get的url设置为AWS API Gateway或Lambda的URL即可。不再需要在Node.js的app.js中编写跨源资源共享(CORS)的头部信息。

广告
将在 10 秒后关闭
bannerAds