ホームページ  >  記事  >  ウェブフロントエンド  >  Node.js 非同期プログラミング コールバック入門 (1)_node.js

Node.js 非同期プログラミング コールバック入門 (1)_node.js

WBOY
WBOYオリジナル
2016-05-16 16:07:121208ブラウズ

Node.js は JavaScript エンジン v8 に基づいており、シングルスレッドです。 Node.js は、Web 上の JavaScript に似た非同期プログラミング メソッドを使用して、I/O 操作のブロックを処理します。 Node.js でのファイルの読み取り、データベースへのアクセス、ネットワーク リクエストなどはすべて非同期である可能性があります。 Node.js を初めて使用する人、または他の言語背景から Node.js に移行する開発者にとって、非同期プログラミングは苦痛な部分です。この章では、最も単純なものからより深いものまで、Node.js 非同期プログラミングのあらゆる側面を紹介します。サンク、プロミス、コへの最も基本的なコールバックから、ES7 で予定されている async/await まで。

まず、非同期プログラミングの具体的な例から始めましょう。

複数の IP ロケーションの気象情報を取得します

ファイル ip.json には、さまざまな場所からのさまざまな訪問者を表す複数の IP アドレスを保存する配列があります。

コードをコピー コードは次のとおりです:

// ip.json
["115.29.230.208"、"180.153.132.38"、"74.125.235.224"、"91.239.201.98"、"60.28.215.115"]

各 IP ロケーションの現在の天気を取得できれば幸いです。結果を次の形式で Weather.json ファイルに出力します:
コードをコピー コードは次のとおりです:

// 天気.json
[
{ "ip": "115.29.230.208", "天気": "雲", "地域": "浙江省" },
{ "ip": "180.153.132.38", "天気": "快晴"、 "地域": "上海" },
{ "ip": "74.125.235.224", "天気": "雨"、 "地域": "カリフォルニア" },
{ "ip": "60.28.215.115"、"天気": "晴れ"、"地域": "天津" }
]

考えを整理するために、次のステップに分けます。

1. IP アドレスを読み取ります。
2. IP アドレスに基づいて IP の地理的位置を取得します。 3. 地理的な位置に基づいて地域の天気を確認します
4. 結果をweather.jsonファイルに書き込みます。

これらの手順はすべて非同期です (ファイルの読み取りと書き込みは同期できますが、例として非同期が使用されます)。

コールバック

まず、Node.js API が通常提供する方法で実装してみます。ライブラリを使用せずにコールバックを非同期コールバックとして渡します。 3 つの基本モジュールを使用します:

1.fs: ファイル ip.json から IP リストを読み取り、結果をファイルに書き込みます。 2.リクエスト: HTTP リクエストを送信し、IP アドレスに基づいて地理データを取得し、地理データを通じて気象データを取得するために使用されます。 3.querystring: リクエストを送信するための URL パラメータを組み立てるために使用されます。


新しい callback.js ファイルを作成し、次のモジュールを導入します:


コードをコピー コードは次のとおりです: // コールバック.js
var fs = require('fs')
var request = require('request')
var qs = require('クエリ文字列')



ファイル内の IP リストを読み取り、fs.readFile を呼び出してファイルの内容を読み取り、JSON.parse を使用して JSON データを解析します。


コードをコピー コードは次のとおりです: ...
関数 readIP(パス, コールバック) {
fs.readFile(path, function(err, data) {
(エラー) {
の場合 コールバック(エラー)
} else {
{
を試してください データ = JSON.parse(data)
コールバック(null, データ)
} キャッチ (エラー) {
コールバック(エラー)
}
}
})
}
...



次のステップは、IP を使用して地理情報を取得することです。リクエストを使用して、オープンな地理サービスをリクエストします。


コードをコピー コードは次のとおりです: ...
function ip2geo(ip, callback) {
var url = 'http://www.telize.com/geoip/' ip
request({
URL: URL、
json: true
}, function(err, resp, body) {
コールバック(err, body)
})
}
...

地理データを使用して天気を取得します:

コードをコピー コードは次のとおりです:

...
関数 geo2weather(lat, lon, callback) {
var params = {
緯度: 緯度、
ロン: ロン、
APPID: '9bf4d2b07c7ddeb780c5b32e636c679d'
}
var url = 'http://api.openweathermap.org/data/2.5/weather?' qs.stringify(params)
request({
URL: URL、
json: true、
}, function(err, resp, body) {
コールバック(err, body)
})
}
...

地理と天気のインターフェイスを取得しましたが、複数の IP があるため、処理する必要がある少し複雑な問題がまだ残っています。
は、地理と天気データを並行して読み取る必要があります。
コードをコピー コードは次のとおりです:

...
function ips2geos(ips, callback) {
var geos = []
var ip
var 残り = ips.length
for (var i = 0; i ip = ips[i];
(関数(ip) {
ip2geo(ip, function(err, geo) {
(エラー) {
の場合 コールバック(err)
} else {
geo.ip = ip
geos.push(geo)
残り--
}
If (残り == 0) {
callback(null, geos)
}
})
})(ip)
}
}

関数 geos2weathers(geos, callback) {
var 天気 = []
var geo
var 残り = geos.length
for (var i = 0; i 地理 = geos[i];
(関数(地理) {
geo2weather(geo.latitude, geo.longitude, function(err, 天気) {
(エラー) {
の場合 コールバック(err)
} else {
天気.geo = 地理
天気.push(天気)
残り--
}
If (残り == 0) {
コールバック(null、天気)
}
})
})(地理)
}
}
...

ips2geos と geos2weathers はどちらも比較的原始的な方法を使用しており、remain が返されるのを待っているアイテムの数を計算します。remain が 0 の場合、並列リクエストが終了したことを意味し、処理結果は配列にロードされて返されます。 。

最後のステップは、結果をweather.jsonファイルに書き込むことです:

コードをコピー コードは次のとおりです:

...
function writeWeather(weathers, callback) {
var 出力 = []
var天気
for (var i = 0; i 天気 = 天気[i]
Output.push({
IP:weather.geo.ip、
天気:weather.weather[0].main,
地域: Weather.geo.region
})
}
fs.writeFile('./weather.json', JSON.stringify(output, null, ' '), callback)
}
...

上記の関数を組み合わせることで、次の目標を達成できます:

コードをコピー コードは次のとおりです:

...
関数 handlerError(err) {
  console.log('エラー: ' エラー)
}

readIP('./ip.json', function(err, ips) {
  if (エラー) {
    ハンドラーエラー(エラー)
  } else {
    ips2geos(ips, function(err, geos) {
      if (エラー) {
        ハンドラーエラー(エラー)
      } else {
        geos2weathers(geos, function(err, 天気) {
          if (エラー) {
            ハンドラーエラー(エラー)
          } else {
            writeWeather(天気, function(err) {
              if (エラー) {
                ハンドラーエラー(エラー)
              } else {
                console.log('成功!')
              }
            })
          }
        })
      }
    })
  }
})

哈哈、この適合ファイルを無視してください、これは JavaScript のセキュリティの問題です、真実です、プラグインは JavaScript のセキュリティの問題ではありません。

复制代码代码如下:
...
関数 ReadIPCallback(err, ips) {
  if (エラー) {
    ハンドラーエラー(エラー)
  } else {
    ips2geos(ips, ips2geosCallback)
  }
}
関数 ips2geosCallback(err, geos) {

  if (エラー) {
    ハンドラーエラー(エラー)
  } else {
    geos2weathers(geos, geos2weathersCallback)
  }
}

関数 geos2weathersCallback(err, 天気) {

  if (エラー) {
    ハンドラーエラー(エラー)
  } else {
    writeWeather(天気、writeWeatherCallback)
  }
}

関数 writeWeatherCallback(err) {

  if (エラー) {
    ハンドラーエラー(エラー)
  } else {
    console.log('成功!')
  }
}

readIP('./ip.json', ReadIPCallback)


よろしくお願いします。これが私たちの callback.js のすべての内容です。実行中:


复制代码代码如下:
ノード callback.js

将会生成 weter.json 文例:

复制代码代码如下:
[
  {
    "ip": "180.153.132.38",
    "天気": "晴れ"、
    "地域": "上海"
  }、
  {
    "ip": "91.239.201.98",
    "天気": "雲"
  }、
  {
    "ip": "60.28.215.115",
    "天気": "晴れ"、
    "地域": "天津"
  }、
  {
    "ip": "74.125.235.224",
    "天気": "雲"、
    "地域": "カリフォルニア"
  }、
  {
    "ip": "115.29.230.208",
    "天気": "晴れ"、
    "地域": "浙江省"
  }
]

では、本当の問題は何でしょうか?

もちろん、これは非同期の問題であり、本質的には次の 3 つのことに対処する必要があります。

1. 非同期操作が終了したら、コールバックで通知する必要があります。

2. 非同期的に生成された結果は、データ パラメータを受け入れて返す必要があります。
3. 非同期エラーが発生した場合はどうすればよいですか?コールバックは err パラメータを受け入れ、エラーを返します。

しかし、繰り返しの作業 (さまざまなコールバック) がたくさんあることに気づきましたか?上記のコードに何か問題はありますか?この記事の続きを楽しみにしていてください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。