ホームページ  >  記事  >  ウェブフロントエンド  >  この記事では、Node.js で軽量の位置分析レポート サービス API を構築する方法について詳しく説明します。

この記事では、Node.js で軽量の位置分析レポート サービス API を構築する方法について詳しく説明します。

青灯夜游
青灯夜游転載
2022-02-23 20:18:571157ブラウズ

この記事では、実践的な経験を共有し、Node で位置分析レポート API を構築する方法を紹介します。このチュートリアルの最後には、エラー処理と でのエラー処理についても説明します。 Node.js のファイル構造が適切であると理解が深まります。皆さんのお役に立てれば幸いです。

この記事では、Node.js で軽量の位置分析レポート サービス API を構築する方法について詳しく説明します。

緯度と経度によって定義される位置を他のデータと組み合わせて、ビジネスのための洞察を生成することができます。これは位置分析と呼ばれます。

世界中で事業を展開している企業は、ユーザーのターゲティング、サービスの提供、ターゲットを絞った広告の実行など、バリュー チェーン全体で位置分析を使用しています。ソーシャル メディアとモバイル デバイスの台頭により、位置分析の使用が世界的に増加しています。

このチュートリアルでは、Node.js で軽量の位置分析レポート サービス API を構築する方法を学習します。このチュートリアルを終えると、独自のプロジェクト用にこのタイプの API を構築できるようになります。また、Node.js でのエラー処理と優れたファイル構造についてもより深く理解できるようになります。

始めましょう!

前提条件

このチュートリアルの学習を続けるには、次のことを行う必要があります。以下の条件を満たしていること。

  • Node.js、Express、Git に精通している方
  • Visual Studio Code Editor
  • Heraku アカウント
  • Postman アカウント

ファイル構造を設定する

まず、ファイル構造を設定する必要があります。ターミナルを開き、プロジェクトのすべてのファイルを保存する新しいディレクトリを作成します。ターミナルで次のコマンドを入力し、その後にフォルダー名 lars を入力します。

mkdir lars

VS コード エディターで lars 作業ディレクトリを開きます。

  code .

VS Code ウィンドウが開いていることがわかります。

この記事では、Node.js で軽量の位置分析レポート サービス API を構築する方法について詳しく説明します。

Visual Studio コード ウィンドウ

Visual Studio でターミナルを開き、 npm init -y を実行して、作業ディレクトリを初期化します。

このコマンドを VS Code 以外のオペレーティング システムのターミナルで実行する場合は、lars ディレクトリに移動し、以下のコマンドを実行します。

npm init -y

上記のコードは、package.json ファイルを自動的に生成します。

この記事では、Node.js で軽量の位置分析レポート サービス API を構築する方法について詳しく説明します。

VS コードには作成された package.json ファイルが表示されます

このチュートリアルでは、Express を依存関係として使用します。以下のコマンドを実行して Express をインストールします。

npm install express --save

この記事では、Node.js で軽量の位置分析レポート サービス API を構築する方法について詳しく説明します。

Express を依存関係としてインストールするコマンド

Express をインストールすると、node_modules フォルダーが作成されることがわかります。 Express がインストールされていることを確認するには、package.json ファイルを確認すると、Express が依存関係としてインストールされていることがわかります。

この記事では、Node.js で軽量の位置分析レポート サービス API を構築する方法について詳しく説明します。

# node_modules フォルダーが作成され、Express が package.json に追加されます。

Express は npm モジュールであるため、アプリケーションにインポートする必要があります。 package.json ファイルと同じディレクトリに app.js という新しいファイルを作成します。

この記事では、Node.js で軽量の位置分析レポート サービス API を構築する方法について詳しく説明します。

VS コード ウィンドウのスクリーンショットは、app.js が作成されたことを示しています。

app.js ファイルで、require次のコードを実行して表現します。

const express = require('express');

この記事では、Node.js で軽量の位置分析レポート サービス API を構築する方法について詳しく説明します。

Import Express

次に、Express を呼び出して、アプリケーション、ルート、およびアプリケーションを実行するポートを作成します。

const app = express();

Node.js はモジュール性を実装しています。つまり、アプリケーションをモジュールまたはさまざまなファイルに分割し、各ファイルをエクスポートします。 export キーワードを使用して app をエクスポートします。

module.exports = app;

この記事では、Node.js で軽量の位置分析レポート サービス API を構築する方法について詳しく説明します。

app.js ファイル

次に、server.js ファイルという名前の別のファイルを作成します。 Require app.js ファイルを server.js ファイルにインポートします。 <pre class="brush:html;toolbar:false;">const app = require(&amp;#39;./app&amp;#39;);</pre>

server.js

と同じディレクトリに config.env という名前のファイルを作成します。 config.env ファイルには、すべての [process.env](https://nodejs.org/dist/latest-v8.x/docs/api/process.html) が含まれます。アプリケーションに必要なすべてのキー。 config.env ファイルで、PORT 変数を作成し、ポート 8000 でリッスンするように PORT を設定します。 <pre class="brush:html;toolbar:false;">PORT=8000</pre><p>导入应用程序后,在<code>server.js 文件中创建一个名为port 的常量。将其设置为你刚刚创建的PORT 变量和一个默认的端口3000

const port = process.env.PORT || 3000;

最后,我们将用.listen() 方法设置应用程序在该端口上监听。

app.listen(port, () => {
    console.log(`App listening on ${port}`)
});

构建路由

每当你访问一个网页或一个在网络上运行的应用程序时,你都在发出一个HTTP请求。服务器用来自后台或数据库的数据进行响应,这就是所谓的HTTP响应。

当你在一个网络应用程序上创建一个资源时,你正在调用POST 请求。同样地,如果你试图删除或更新一个Web应用上的资源,你正在调用DELETEPATCH 、或UPDATE 请求。让我们建立路由来处理这些请求。

在你的工作目录中创建一个名为routes 的文件夹,并在其中创建一个名为analyticsRoute.js 的文件。RequireanalyticsRoute.js 文件中表达,以设置API的路由。

      const express = require(&#39;express&#39;);

我们还需要从app.js 文件中require 我们的应用程序模块。

        const app = require(&#39;../app&#39;);

然后,我们创建我们的路由。

        const router = express.Router();

最后,我们要导出路由器。

        module.exports = router;

建立控制器

我们需要为控制器创建文件,将其导入我们的analyticsRoutes 文件。首先,在你的工作目录中创建一个名为controllers 的文件夹。

我们的API将使用用户提供的IP地址和坐标来计算距离和位置。我们的请求需要接受这些信息和来自用户的请求。

我们将使用一个POST 请求,因为用户在req.body 。为了保存这些信息,我们需要在控制器中require 一个fs 模块(文件系统)。

处理POST 的请求

controllers 文件夹中创建一个名为storeController.js 的文件。在storeController.js 文件中,我们需要导入fs 模块和fsPromises.readFile() 方法来处理返回的promise ,也就是用户的IP地址和坐标。

要安装fs 模块,在你的工作目录中打开你的终端,运行以下命令。

npm i fs --save

在你的文件顶部输入以下代码。

const fsp = require(&#39;fs&#39;).promises;
const fs = require(&#39;fs&#39;);

接下来,我们将创建一个控制器,处理我们的POST 请求的路由。我们将使用exports 关键字并创建一个接受三个参数的异步中间件函数

  • req: 代表请求对象
  • res: 代表响应对象
  • next: 函数在中间件输出后立即被调用。
postAnalytics = async(req, res, next) => {}

现在,我们将把req.body 中的数据对象的属性保存到reportAnalytics 数组中。我们将设置一个Date() 对象,将任何数据的创建日期保存在一个createdAt 关键中。

reportAnalytics.push({...req.body, createdAt: new Date()});

我们将创建一个名为storeAnalytics.json 的文件,使用JSON.stringify() ,将我们的reportAnalytics 数组的内容保存为一个字符串。

 await fsp.writeFile(`${__dirname}/storeAnalytics.json`, JSON.stringify(reportAnalytics));

当用户提出POST 要求时,我们需要检查storeAnalytics.json 文件是否存在。如果该文件存在,我们需要读取该文件并保存输出。

输出包含一个名为reportFile 的常量,它存储了被读取的文件内容。在reportFile ,使用JSON.parse ,将文件的内容转换为一个JavaScript对象。

// checks if file exists
if (fs.existsSync(`${__dirname}/storeAnalytics.json`)) {
// If the file exists, reads the file
  const reportFile = await fsp.readFile(`${__dirname}/storeAnalytics.json`, &#39;utf-8&#39;)
// converts the file to JavaScript Object
reportAnalytics = JSON.parse(reportFile)
} else {
  // if file does not exist
   return (&#39;File does not exist&#39;);
}

[fs.existsSync()](https://www.geeksforgeeks.org/node-js-fs-existssync-method/)方法同步地检查文件是否存在。它接受${__dirname}/storeAnalytics.json 路径作为其单一参数,并指向我们要检查的文件的位置。

我们将await 关键字与reportFile ,以等待用fsp.readFile() 方法读取文件的结果。接下来,我们用(${__dirname}/storeAnalytics.json 来指定我们要读取的文件的路径。我们将编码格式设置为utf-8 ,这将把从文件中读取的内容转换为一个字符串。

JSON.parse()reportFile 转换为JavaScript对象,并将其存储在reportAnalytics 数组中。else 语句块中的代码只有在文件不存在时才会运行。最后,我们使用了return 语句,因为我们想在代码运行后停止函数的执行。

如果文件被成功读取、创建并保存在storeAnalytics.json ,我们需要发送一个响应。我们将使用响应对象(res) ,它是我们的异步postAnalytics 函数的第二个参数。

    res.status(201).json({
        status: &#39;success&#39;,
        data: {
            message: &#39;IP and Coordinates successfully taken&#39;
        }
    })

我们将用一个状态success 和数据信息IP and Coordinates successfully taken 来响应。

你的storeController.js 文件应该看起来像下面的屏幕截图。

この記事では、Node.js で軽量の位置分析レポート サービス API を構築する方法について詳しく説明します。

处理GET 的请求

我们需要创建另一个控制器文件来处理我们的GET 请求。当用户向API发出GET 请求时,我们将根据他们的IP地址和坐标来计算他们的位置。

controllers 文件夹中创建一个名为fetchController.js 的文件。fsstoreController.js 文件中,我们需要require 模块和fsPromises.readFile() 方法来处理返回的promise

const fsp = require(&#39;fs&#39;).promises;
const fs = require(&#39;fs&#39;);

让我们创建控制器来处理我们对GET 请求的路由。我们将使用类似的中间件函数和参数来处理上面的POST 请求。

   exports.getAnalytics = async(req, res, next) => {}

getAnalytics 中间件中,输入以下代码,从请求的查询中获得IP地址。

     const { ip } = req.query;

现在,创建一个空数组,用来存储req.body 的内容。

     let reportAnalytics = [];

正如我们之前所做的,我们需要检查storeAnalytics.json 文件是否存在。如果文件存在,我们将在reportFile 上使用JSON.parse ,将文件内容转换为一个JavaScript对象。

if (fs.existsSync(`${__dirname}/storeAnalytics.json`)) {
        const reportFile = await fsp.readFile(`${__dirname}/storeAnalytics.json`, &#39;utf-8&#39;)
        reportAnalytics = JSON.parse(reportFile)
    } else {
        return (&#39;File does not exist&#39;);
    }

现在,我们可以在storeAnalytics.json 文件中保存用户的IP地址和坐标。任何时候用户请求根据提供的坐标计算地理位置,IP地址将以查询的形式包含在请求中。

现在我们已经从req.query 对象中得到了IP地址,我们可以编写代码来检查req.query 对象中提供的IP地址是否与存储在storeAnalytics.json 文件中的IP地址相同。

   for (let i=0; i<reportAnalytics.length; i++) {
        if (reportAnalytics[i].ip !== ip) {
           return (&#39;No Coordinates found with that IP&#39;);
        };
    }

在上面的代码中,我们使用forloop 来循环浏览reportAnalytics 数组。我们将变量i ,代表当前元素在reportAnalytics 数组中的索引,初始化为0 。如果i小于reportAnalytics 数组的长度,我们将其递增。

接下来,我们检查reportAnalytics 数组的IP地址属性是否等于req.query 中提供的IP地址。

让我们计算一下只在最后一小时内存储的IP地址的位置。

    const hourAgo = new Date();
    hourAgo.setHours(hourAgo.getHours()-1);
    const getReport = reportAnalytics.filter(el => 
        el.ip === ip && new Date(el.createdAt) > hourAgo
    )

在上面的代码块中,我们创建了一个名为hourAgo 的常量,并将其设置为一个Date 对象。我们使用setHours() 方法将hourAgo 设置为最后一个小时的getHours()-1

reportAnalytics 文件中的当前IP地址等同于或等于req.query 中传递的IP地址时,意味着数据是在最后一小时内创建的,getReport 创建一个常量,设置为一个新的数组。

创建一个名为coordinatesArray 的常量,它将只存储已经保存在getReport 数组中的坐标。

const coordinatesArray = getReport.map(element => element.coordinates)

接下来,我们需要用坐标计算出位置。我们需要遍历coordinatesArray ,通过传入保存为坐标的两个值来计算位置。

    let totalLength = 0;
    for (let i=0; i<coordinatesArray.length; i++) {
        if (i == coordinatesArray.length - 1) {
            break;
        }
        let distance = calculateDistance(coordinatesArray[i], coordina         tesArray[i+1]);
        totalLength += distance;
    }

在上面的代码中,totalLength 代表从两个坐标计算出来的总距离。为了遍历coordinatesArray ,我们需要初始化我们的计算结果。将totalLength 设置为零,初始化总距离。

第二行包含我们使用的迭代代码forloop 。我们用let i=0 来初始化i 变量。i 变量代表当前元素在coordinatesArray 的索引。

i<coordinatesarray.length> 设置迭代的条件,只有当当前元素的索引小于<code>coordinatesArray 的长度时才运行。接下来,我们在迭代中增加当前元素的索引,以移动到下一个元素,i++

接下来,我们将检查当前元素的索引是否等于数组中最后一个元素的编号。然后,我们暂停迭代代码的执行,用break 关键字移动到下一个。

最后,我们创建一个名为calculateDistance 的函数,接受两个参数,即第一和第二坐标值(经度和纬度)。我们将在另一个模块中创建calculateDistance ,并将其导出到fetchController.js 文件中,然后我们将最终结果保存在我们初始化的totalLength 变量中。

注意,每个请求都需要一个响应。我们将用一个200statusCode 和一个包含我们将计算的距离值的JSON来响应。只有在代码成功的情况下才会显示响应。

     res.status(200).json({distance: totalLength})

你的fetchController.js 文件应该看起来像下面两个代码块。

この記事では、Node.js で軽量の位置分析レポート サービス API を構築する方法について詳しく説明します。

fetchController.js文件

この記事では、Node.js で軽量の位置分析レポート サービス API を構築する方法について詳しく説明します。

fetchController.js文件的续篇

建立calculateDistance 函数

在你的工作目录中,创建一个名为utilities 的新文件夹,在里面创建一个名为calculateDistance.js 的文件。打开calculateDistance.js 文件,添加以下函数。

const calculateDistance = (coordinate1, coordinate2) => {
    const distance = Math.sqrt(Math.pow(Number(coordinate1.x) - Number(coordinate2.x), 2) + Math.pow(Number(coordinate1.y) - Number(coordinate2.y), 2));
    return distance;
} 
module.exports = calculateDistance;

在第一行,我们创建一个名为calculateDistance 的函数,它接受两个参数:coordinate1coordinate2 。它使用下面的方程式。

  • Math.sqrt: 数学中的平方根
  • Math.pow :将一个数字提高到一个幂值
  • Number(): 将一个值转换为一个数字
  • coordinate1.x :第一个坐标(经度)的第二个值
  • coordinate2.x :第一个坐标的第一个值(经度)。
  • coordinate1.y :第二个坐标的第二个值(纬度)。
  • coordinate2.y :第二个坐标的第一个值(纬度)。

现在我们已经创建了calculateDistance 函数,我们需要将该函数require 到我们fetchController.js 文件的代码中。在fs 模块之后添加下面的代码。

const calculateDistance = require(&#39;../utilities/calculateDistance&#39;);

实现错误处理

实现错误处理是很重要的,以防止我们的代码失败或某个特定的实现没有按照设计的方式工作。我们将在开发和生产中添加错误处理。

打开你的config.env 文件,运行NODE_ENV=development ,将环境设置为开发。

在你的controllers 文件夹中,创建一个名为errorController.js 的新文件。下面的代码片断创建了一个名为sendErrorDev 的函数,以处理在开发环境中遇到的错误。

const sendErrorDev = (err, res) => {
    res.status(err.statusCode).json({
        status: err.status,
        error: err,
        message: err.message,
        stack: err.stack,
    });
}

我们将创建一个名为sendErrorDev 的函数,它接受两个参数,err 表示错误,res 表示响应。response.status 接收错误的statusCode ,并以JSON数据进行响应。

此外,我们将创建一个名为sendErrorProd 的函数,它将处理API在生产环境中遇到的错误。

const sendErrorProd = (err, res) => {
    if(err.isOperational) {
        res.status(err.statusCode).json({
            status: err.status,
            message: err.message
        });    
    } else {
        console.error(&#39;Error&#39;, err);
        res.status(500).json({
            status: &#39;error&#39;,
            message: &#39;Something went wrong&#39;
        })
    }
}

在你的utilities 文件夹中,创建一个名为appError.js 的文件,并输入以下代码。

class AppError extends Error {
    constructor(message, statusCode) {
        super(message);
        this.statusCode = statusCode;
        this.status = `${statusCode}`.startsWith(&#39;4&#39;) ? &#39;fail&#39; : &#39;error&#39;;
        this.isOperational = true;
        Error.captureStackTrace(this, this.constructor);
    }
}
module.exports = AppError;

我们将创建一个名为AppError 的类,它扩展了Error 对象。

然后,我们将创建一个构造函数,它将初始化该类的对象。它接受两个参数,叫做messagestatusCodesuper 方法用一个参数调用构造函数,将其传入message ,并获得对构造函数的属性和方法的访问。

接下来,我们将构造函数的statusCode 属性设置为statusCode 。我们将构造函数的status 属性设置为任何以4 开始的statusCode ,例如,将404 statusCode 设置为failerror

创建另一个名为catchAsync.js 的文件,并在其中添加以下代码。

module.exports = fn => {
    return (req, res, next) => {
        fn(req, res, next).catch(next);
    }
}

在控制器文件中添加错误处理

Require appError.js 文件和catchAsync.js 文件在你的storeController.jsfetchController.js 文件中。将这两条导入语句放在两个文件中的代码顶部。

const catchAsync = require(&#39;../utilities/catchAsync&#39;);
const AppError = require(&#39;../utilities/appError&#39;);

storeController.jsfetchController.js 文件中,用catchAsync() 方法包装你的函数,如下所示。

// For storeController.js file
exports.postAnalytics = catchAsync(async(req, res, next) => {...} 

// For fetchController.js file
exports.getAnalytics = catchAsync(async(req, res, next) => {...}

接下来,在你的fetchController.js 文件中,运行AppError 类。

   for (let i=0; i<reportAnalytics.length; i++) {
        if (reportAnalytics[i].ip !== ip) {
           return next(new AppError(&#39;No Coordinates found with that IP&#39;, 404));
        };
    }

接下来,在你的storeController.js 文件中运行AppError 类。

   if (fs.existsSync(`${__dirname}/storeAnalytics.json`)) {
        const reportFile = await fsp.readFile(`${__dirname}/storeAnalytics.json`, &#39;utf-8&#39;)
        reportAnalytics = JSON.parse(reportFile)
    } else {
        return next(new AppError(&#39;File does not exist&#39;, 404));
    }

你的storeController.jsfetchController.js 文件中的代码应该看起来像下面的截图。

1この記事では、Node.js で軽量の位置分析レポート サービス API を構築する方法について詳しく説明します。

storeController.js文件的屏幕截图

1この記事では、Node.js で軽量の位置分析レポート サービス API を構築する方法について詳しく説明します。

fetchController.js文件第1-32行

1この記事では、Node.js で軽量の位置分析レポート サービス API を構築する方法について詳しく説明します。

fetchController.js文件第33-37行

设置验证

我们需要验证在req.body ,其中包括IP地址和坐标的数据,是正确的,而且格式正确。坐标应该至少有两个值,代表经度和纬度。

utilities 文件夹中,创建一个名为Validation 的新文件夹。在Validation 文件夹中,创建一个名为schema.js 的文件。schema.js 文件将包含req.body 中提供的任何数据的所需格式。我们将使用 [joi](https://www.npmjs.com/package/joi)验证器。

npm install joi

schema.js 文件中输入以下代码。

const Joi = require(&#39;joi&#39;);
const schema = Joi.object().keys({
    ip: Joi.string().ip().required(),
    coordinates: Joi.object({
        x: Joi.number().required(),
        y: Joi.number().required()
    }).required()
})
module.exports = schema;

joi 在上面的代码块中,我们require 验证器,用它来创建我们的模式。然后,我们将IP地址设置为总是一个字符串,并通过在请求体中要求它来验证IP地址。

我们将坐标设置为object 。我们将代表经度和纬度值的xy 值都设置为数字,并将其require ,以便我们的代码运行。最后,我们导出了模式。

在验证器文件夹中,创建另一个名为validateIP.js 的文件。在里面,我们将编写代码来验证IP地址,使用 [is-ip](https://www.npmjs.com/package/is-ip)npm包。让我们把这个包导出到我们的代码中。

validateIP.js 文件中,添加以下代码。

const isIp = require('is-ip');
const fsp = require(&#39;fs&#39;).promises;
const fs = require(&#39;fs&#39;);
exports.validateIP = (req, res, next) => {
    if(isIp(req.query.ip) !== true) {
        return res.status(404).json({
            status: 'fail',
            data: {
                message: 'Invalid IP, not found.'
            }
        })
    }
    next();
}

运行以下命令,为我们的API安装必要的依赖项。

npm install body-parser cors dotenv express fs is-ip joi morgan ndb nodemon

你的app.js 文件应该看起来像下面的屏幕截图。

1この記事では、Node.js で軽量の位置分析レポート サービス API を構築する方法について詳しく説明します。

app.js文件

在你的package.json 文件中的scripts 部分下,添加以下代码片段。

"start:dev": "node server.js",
    "debug": "ndb server.js"

你的package.json 文件应该看起来像下面的截图。

1この記事では、Node.js で軽量の位置分析レポート サービス API を構築する方法について詳しく説明します。

package.json文件

用以下代码更新你的analyticsRoute.js 文件。

const express = require(&#39;express&#39;);
const app = require('../app');
const router = express.Router();
const validateIP = require('../utilities/Validation/validateIP');
const storeController = require('../controllers/storeController');
const fetchController = require('../controllers/fetchController');
router.route('/analytics').post(storeController.postAnalytics).get(validateIP.validateIP, fetchController.getAnalytics);
module.exports = router;

现在,我们已经完成了我们的位置分析API的构建!现在,让我们测试一下我们的代码,以确保它的工作。

测试API

我们将使用Postman来测试我们的API。让我们启动我们的API以确保它在我们的终端中运行。

node server.js

你会在你的终端看到以下输出。

1この記事では、Node.js で軽量の位置分析レポート サービス API を構築する方法について詳しく説明します。

终端

我们的API托管在Heroku上,它的最终输出应该看起来像下面的输出。

1この記事では、Node.js で軽量の位置分析レポート サービス API を構築する方法について詳しく説明します。

你可以自己在托管的文档中测试这个API

https://documenter.getpostman.com/view/13856921/TzXumeXS

结论

位置分析是企业的一个伟大工具。位置信息可以让公司更好地服务于潜在客户和现有客户。

このチュートリアルでは、IP アドレスと座標の形式で位置情報を取得し、距離を計算するツールを構築する方法を学びました。 Node.js でファイル構造を設定し、GET および POST リクエストを処理するためのルートを確立し、エラー処理を追加して、最後にアプリケーションをテストしました。

このチュートリアルで学んだ情報を使用して、ビジネス ニーズに合わせてカスタマイズできる独自の位置レポート API を構築できます。

この投稿Node.js でロケーション分析レポート API を構築する appeared first on LogRocket Blog.

ノード関連の知識について詳しくは、こちらをご覧ください。訪問: nodejs チュートリアル!

以上がこの記事では、Node.js で軽量の位置分析レポート サービス API を構築する方法について詳しく説明します。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjuejin.cnで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。