Rumah  >  Artikel  >  hujung hadapan web  >  Node.js Asynchronous Programming Callback Pengenalan (1)_node.js

Node.js Asynchronous Programming Callback Pengenalan (1)_node.js

WBOY
WBOYasal
2016-05-16 16:07:121208semak imbas

Node.js adalah berdasarkan enjin JavaScript v8 dan berbenang tunggal. Node.js menggunakan kaedah pengaturcaraan tak segerak yang serupa dengan JavaScript di Web untuk mengendalikan operasi I/O yang menyekat. Membaca fail, mengakses pangkalan data, permintaan rangkaian, dsb. dalam Node.js semuanya mungkin tidak segerak. Bagi mereka yang baru menggunakan Node.js atau pembangun yang berhijrah ke Node.js daripada latar belakang bahasa lain, pengaturcaraan tak segerak adalah bahagian yang menyakitkan. Bab ini akan memperkenalkan anda kepada semua aspek pengaturcaraan tak segerak Node.js daripada yang paling mudah kepada yang lebih mendalam. Daripada panggilan balik yang paling asas kepada thunk, Promise, co kepada async/menunggu yang dirancang untuk ES7.

Pertama, mari kita mulakan dengan contoh khusus pengaturcaraan tak segerak.

Dapatkan maklumat cuaca untuk berbilang lokasi IP

Dalam fail ip.json, terdapat tatasusunan di mana kami menyimpan beberapa alamat IP, yang merupakan pelawat yang berbeza dari tempat yang berbeza Kandungannya adalah seperti berikut:

Salin kod Kod adalah seperti berikut:

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

Saya harap saya boleh mendapatkan cuaca semasa untuk setiap lokasi IP. Keluarkan keputusan ke fail weather.json dalam format berikut:
Salin kod Kod adalah seperti berikut:

// weather.json
[
{ "ip": "115.29.230.208", "cuaca": "Awan", "rantau": "Zhejiang" },
{ "ip": "180.153.132.38", "cuaca": "Jelas", "rantau": "Shanghai" },
{ "ip": "74.125.235.224", "cuaca": "Hujan", "rantau": "California" },
{ "ip": "60.28.215.115", "cuaca": "Jelas", "rantau": "Tianjin" }
]

Untuk menyusun pemikiran kami, kami membahagikannya kepada langkah-langkah berikut:

1. Baca alamat ip; 2. Dapatkan lokasi geografi IP berdasarkan alamat IP; 3. Semak cuaca tempatan berdasarkan lokasi geografi; 4. Tulis keputusan ke fail weather.json.

Langkah ini semuanya tak segerak (membaca dan menulis fail boleh segerak, tetapi sebagai contoh, tak segerak digunakan).

panggil balik

Pertama, kami cuba melaksanakannya mengikut cara yang biasanya disediakan oleh Node.js API - menghantar panggilan balik sebagai panggilan balik tak segerak tanpa menggunakan sebarang pustaka. Kami akan menggunakan tiga modul asas:

1.fs: Baca senarai IP daripada fail ip.json; 2.permintaan: digunakan untuk menghantar permintaan HTTP, mendapatkan data geo berdasarkan alamat IP, dan kemudian mendapatkan data cuaca melalui data geo; 3.querystring: digunakan untuk memasang parameter url untuk menghantar permintaan.

Buat fail callback.js baharu dan perkenalkan modul ini:



Salin kod

Kod adalah seperti berikut: // callback.js var fs = memerlukan('fs') var request = memerlukan('request')
var qs = memerlukan('querystring')



Baca senarai IP dalam fail, panggil fs.readFile untuk membaca kandungan fail, dan kemudian gunakan JSON.parse untuk menghuraikan data JSON:

Salin kod

Kod adalah seperti berikut: ... function readIP(path, callback) { fs.readFile(laluan, fungsi(err, data) {
Jika (err) {
       panggil balik(err)
} lain {
Cuba {
         data = JSON.parse(data)
         panggil balik(null, data)
} tangkap (ralat) {
        panggil balik(ralat)
}
}
})
}
...



Langkah seterusnya ialah menggunakan IP untuk mendapatkan geo Kami menggunakan permintaan untuk meminta perkhidmatan geo terbuka:

Salin kod

Kod adalah seperti berikut: ... fungsi ip2geo(ip, panggil balik) { var url = 'http://www.telize.com/geoip/' ip
permintaan ({
url: url,
json: benar
}, fungsi(err, resp, body) {
​ panggil balik(err, body)
})
}
...

Gunakan data geo untuk mendapatkan cuaca:

Salin kod Kod adalah seperti berikut:

...
fungsi geo2weather(lat, lon, panggil balik) {
var params = {
lat: lat,
lon: lon,
APPID: '9bf4d2b07c7ddeb780c5b32e636c679d'
}
var url = 'http://api.openweathermap.org/data/2.5/weather?' qs.stringify(params)
permintaan ({
url: url,
json: benar,
}, fungsi(err, resp, body) {
​ panggil balik(err, body)
})
}
...

Memandangkan kami telah memperoleh antara muka untuk geo dan cuaca, kami masih mempunyai masalah yang lebih rumit untuk ditangani Kerana terdapat berbilang IP, kami perlu membaca geo secara selari dan membaca data cuaca secara selari:
Salin kod Kod adalah seperti berikut:

...
fungsi ips2geos(ips, panggil balik) {
var geos = []
var ip
var kekal = ips.length
untuk (var i = 0; i < ips.length; i ) {
ip = ips[i];
(fungsi(ip) {
ip2geo(ip, fungsi(err, geo) {
Jika (err) {
          panggil balik(err)
         } lain {
          geo.ip = ip
           geos.push(geo)
             kekal--
}
Jika (kekal == 0) {
           panggil balik(null, geos)
}
})
})(ip)
}
}

fungsi geos2weathers(geos, panggil balik) {
var weathers = []
var geo
var kekal = geos.length
untuk (var i = 0; i < geos.length; i ) {
Geo = geos[i];
(fungsi(geo) {
geo2weather(geo.latitud, geo.longitud, fungsi(err, cuaca) {
Jika (err) {
          panggil balik(err)
         } lain {
weather.geo = geo
cuaca.tolak(cuaca)
             kekal--
}
Jika (kekal == 0) {
            panggil balik(null, weathers)
}
})
})(geo)
}
}
...

Kedua-dua ips2geos dan geos2weathers menggunakan kaedah yang agak primitif, kekal untuk mengira bilangan item yang menunggu untuk dipulangkan Jika kekal ialah 0, ini bermakna permintaan selari telah tamat dan hasil pemprosesan dimuatkan ke dalam tatasusunan dan dikembalikan. .

Langkah terakhir ialah menulis keputusan ke dalam fail weather.json:

Salin kod Kod adalah seperti berikut:

...
fungsi writeWeather(cuaca, panggil balik) {
var output = []
cuaca var
untuk (var i = 0; i < weathers.length; i ) {
cuaca = cuaca[i]
Output.push({
IP: weather.geo.ip,
Cuaca: weather.weather[0].utama,
Rantau: weather.geo.region
})
}
fs.writeFile('./weather.json', JSON.stringify(output, null, ' '), panggil balik)
}
...

Dengan menggabungkan fungsi di atas, kami boleh mencapai matlamat kami:

Salin kod Kod adalah seperti berikut:

...
fungsi pengendaliRalat(err) {
  console.log('error: ' err)
}

readIP('./ip.json', function(err, ips) {
  jika (err) {
    handlerError(err)
  } lain {
    ips2geos(ips, fungsi(err, geos) {
      jika (err) {
        handlerError(err)
      } lain {
        geos2weathers(geos, fungsi(err, cuaca) {
          jika (err) {
            handlerError(err)
          } lain {
            writeWeather(cuaca, fungsi(err) {
              jika (err) {
                handlerError(err)
              } lain {
                console.log('berjaya!')
              }
            })
          }
        })
      }
    })
  }
})

哈哈,你妈这嵌套,你可能觉得这就是 JavaScript 异步的问题,说真的,嵌套不是 JavaScript 异步的问题,说真的,嵌套不是 JavaScript 异步的问题。这段代码我们可以下面这样写:

复制代码 代码如下:

...
fungsi ReadIPCallback(err, ips) {
  jika (err) {
    handlerError(err)
  } lain {
    ips2geos(ips, ips2geosCallback)
  }
}

fungsi ips2geosCallback(err, geos) {
  jika (err) {
    handlerError(err)
  } lain {
    geos2weathers(geos, geos2weathersCallback)
  }
}

fungsi geos2weathersCallback(err, weathers) {
  jika (err) {
    handlerError(err)
  } lain {
    writeWeather(cuaca, tulisWeatherCallback)
  }
}

fungsi writeWeatherCallback(err) {
  jika (err) {
    handlerError(err)
  } lain {
    console.log('berjaya!')
  }
}

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

好了,这是我们 panggilan balik.js 的全部内容。运行:

复制代码 代码如下:

nod panggil balik.js

将会生成 weater.json 文件:
复制代码 代码如下:

[
  {
    "ip": "180.153.132.38",
    "cuaca": "Jelas",
    "rantau": "Shanghai"
  },
  {
    "ip": "91.239.201.98",
    "cuaca": "Awan"
  },
  {
    "ip": "60.28.215.115",
    "cuaca": "Jelas",
    "rantau": "Tianjin"
  },
  {
    "ip": "74.125.235.224",
    "cuaca": "Awan",
    "rantau": "California"
  },
  {
    "ip": "115.29.230.208",
    "cuaca": "Jelas",
    "wilayah": "Zhejiang"
  }
]

Lalu apa masalah sebenarnya?

Sudah tentu ia adalah masalah asynchronous pada asasnya perlu berurusan dengan tiga perkara:

1. Apabila operasi asynchronous tamat, ia perlu dimaklumkan semula ialah penyelesaian
2. Hasil yang dijana secara tidak segerak perlu dihantar kembali menerima parameter data dan menghantar kembali data; 3. Apakah yang perlu saya lakukan jika ralat tak segerak berlaku? Panggilan balik menerima parameter ralat dan mengembalikan ralat.

Tetapi adakah anda telah menemui banyak kerja berulang (pelbagai panggilan balik)? Adakah terdapat apa-apa yang salah dengan kod di atas? Sila nantikan sambungan artikel ini.

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn