亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 語言 > JavaScript > 正文

Node.js 異步編程之 Callback介紹(一)

2024-05-06 16:17:48
字體:
來源:轉載
供稿:網友
這篇文章主要介紹了Node.js 異步編程之 Callback介紹(一),本文用實例講解Callback的相關知識,本文是第一篇,下一篇小編會跟進,需要的朋友可以參考下
 

Node.js 基于 JavaScript 引擎 v8,是單線程的。Node.js 采用了與通常 Web 上的 JavaScript 異步編程的方式來處理會造成阻塞的I/O操作。在 Node.js 中讀取文件、訪問數據庫、網絡請求等等都有可能是異步的。對于 Node.js 新人或者從其他語言背景遷移到 Node.js 上的開發者來說,異步編程是比較痛苦的一部分。本章將由淺入深為大家講解 Node.js 異步編程的方方面面。從最基礎的 callback 到 thunk、Promise、co 直到 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 這個文件中各式如下:
復制代碼代碼如下:

// weather.json
[
  { "ip": "115.29.230.208", "weather": "Clouds", "region": "Zhejiang" },
  { "ip": "180.153.132.38", "weather": "Clear", "region": "Shanghai" },
  { "ip": "74.125.235.224", "weather": "Rain", "region": "California" },
  { "ip": "60.28.215.115", "weather": "Clear", "region": "Tianjin" }
]

 

整理思路,我們分成以下幾步來完成:

1.讀取 ip 地址;
2.根據 ip 地址獲取 ip 所在地的地理位置;
3.根據地理位置查詢當地的天氣;
4.將結果寫入到 weather.json 文件中。

這些步驟都是異步的(讀寫文件可以同步,但作為示例,都用異步)。

callback

首先我們嘗試不借助任何庫,試著以 Node.js API 通常提供的方式——專遞一個 callback 作為異步回調——來實現。我們將借助三個基礎模塊:

1.fs:從文件 ip.json 讀取 IP 列表;把結果寫入到文件中;
2.request:用來發送 HTTP 請求,根據 IP 地址獲取 geo 數據,再通過 geo 數據獲取天氣數據;
3.querystring:用來組裝發送請求的 url 參數。

新建一個 callback.js 文件,引入這幾個模塊:

復制代碼代碼如下:

// callback.js
var fs = require('fs')
var request = require('request')
var qs = require('querystring')

 

讀取文件中的 IP 列表,調用 fs.readFile 讀取文件內容,再通過 JSON.parse 來解析 JSON 數據:

復制代碼代碼如下:

...
function readIP(path, callback) {
  fs.readFile(path, function(err, data) {
    if (err) {
      callback(err)
    } else {
      try {
        data = JSON.parse(data)
        callback(null, data)
      } catch (error) {
        callback(error)
      }
    }
  })
}
...

 

接著就是使用 IP 來獲取geo,我們使用 request 來請求一個開放的 geo 服務:

復制代碼代碼如下:

...
function ip2geo(ip, callback) {
  var url = 'http://www.telize.com/geoip/' + ip
  request({
    url: url,
    json: true
  }, function(err, resp, body) {
    callback(err, body)
  })
}
...

 

使用 geo 數據來獲取 weather:

復制代碼代碼如下:

...
function geo2weather(lat, lon, callback) {
  var params = {
    lat: lat,
    lon: lon,
    APPID: '9bf4d2b07c7ddeb780c5b32e636c679d'
  }
  var url = 'http://api.openweathermap.org/data/2.5/weather?' + qs.stringify(params)
  request({
    url: url,
    json: true,
  }, function(err, resp, body) {
    callback(err, body)
  })
}
...

現在我們已經獲取 geo、獲取 weather 的接口,接下來我們還有稍微復雜的問題要處理,因為 ip 有多個,所以我們需要并行地去讀取 geo 已經并行地讀取 weather 數據:
復制代碼代碼如下:

...
function ips2geos(ips, callback) {
  var geos = []
  var ip
  var remain = ips.length
  for (var i = 0; i < ips.length; i++) {
    ip = ips[i];
    (function(ip) {
      ip2geo(ip, function(err, geo) {
        if (err) {
          callback(err)
        } else {
          geo.ip = ip
          geos.push(geo)
          remain--
        }
        if (remain == 0) {
          callback(null, geos)
        }
      })
    })(ip)
  }
}

 

function geos2weathers(geos, callback) {
  var weathers = []
  var geo
  var remain = geos.length
  for (var i = 0; i < geos.length; i++) {
    geo = geos[i];
    (function(geo) {
      geo2weather(geo.latitude, geo.longitude, function(err, weather) {
        if (err) {
          callback(err)
        } else {
          weather.geo = geo
          weathers.push(weather)
          remain--
        }
        if (remain == 0) {
          callback(null, weathers)
        }
      })
    })(geo)
  }
}
...

 

ips2geos 和 geos2weathers 都使用了一種比較原始的方法,remain 來計算等待返回的個數,remain 為 0 表示并行請求結束,將處理結果裝進一個數組返回。

最后就是將結果寫入到 weather.json 文件中:

復制代碼代碼如下:

...
function writeWeather(weathers, callback) {
  var output = []
  var weather
  for (var i = 0; i < weathers.length; i++) {
    weather = weathers[i]
    output.push({
      ip: weather.geo.ip,
      weather: weather.weather[0].main,
      region: weather.geo.region
    })
  }
  fs.writeFile('./weather.json', JSON.stringify(output, null, '  '), callback)
}
...

 

組合上面這些函數,我們就可以實現我們的目標:

復制代碼代碼如下:

...
function handlerError(err) {
  console.log('error: ' + err)
}

 

readIP('./ip.json', function(err, ips) {
  if (err) {
    handlerError(err)
  } else {
    ips2geos(ips, function(err, geos) {
      if (err) {
        handlerError(err)
      } else {
        geos2weathers(geos, function(err, weathers) {
          if (err) {
            handlerError(err)
          } else {
            writeWeather(weathers, function(err) {
              if (err) {
                handlerError(err)
              } else {
                console.log('success!')
              }
            })
          }
        })
      }
    })
  }
})

 

哈哈,你媽這嵌套,你可能覺得這就是 JavaScript 異步的問題,說真的,嵌套不是 JavaScript 異步的真正問題所在。上面這段代碼我們可以下面這樣寫:

復制代碼代碼如下:

...
function ReadIPCallback(err, ips) {
  if (err) {
    handlerError(err)
  } else {
    ips2geos(ips, ips2geosCallback)
  }
}

 

function ips2geosCallback(err, geos) {
  if (err) {
    handlerError(err)
  } else {
    geos2weathers(geos, geos2weathersCallback)
  }
}

function geos2weathersCallback(err, weathers) {
  if (err) {
    handlerError(err)
  } else {
    writeWeather(weathers, writeWeatherCallback)
  }
}

function writeWeatherCallback(err) {
  if (err) {
    handlerError(err)
  } else {
    console.log('success!')
  }
}

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

 

好了,這是我們 callback.js 的全部內容。運行:

復制代碼代碼如下:

node callback.js

將會生成 weater.json 文件:
復制代碼代碼如下:

[
  {
    "ip": "180.153.132.38",
    "weather": "Clear",
    "region": "Shanghai"
  },
  {
    "ip": "91.239.201.98",
    "weather": "Clouds"
  },
  {
    "ip": "60.28.215.115",
    "weather": "Clear",
    "region": "Tianjin"
  },
  {
    "ip": "74.125.235.224",
    "weather": "Clouds",
    "region": "California"
  },
  {
    "ip": "115.29.230.208",
    "weather": "Clear",
    "region": "Zhejiang"
  }
]

 

那正真的問題是什么?

當然是異步的問題啦,異步本質上要處理三個事情:

1.異步操作什么時候結束,需要通知回來,Callback 是一種方案;
2.異步產生的結果需要傳遞回來,Callback 接受一個 data 參數,把數據傳回來;
3.異步如果出錯了怎么辦?Callback 接受 一個 err 參數,把錯誤傳回來。

但有沒有發現好多重復的工作(各種 callback)?上面的這些代碼有什么問題么?請大家期待本文的續篇。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产v综合v亚洲欧美久久| 日韩久久免费电影| 日本国产一区二区三区| 日韩免费观看高清| 91人成网站www| 亚洲欧美在线免费观看| 性欧美激情精品| 在线精品视频视频中文字幕| 久久精品视频在线播放| 在线视频中文亚洲| 久久这里有精品视频| 韩国三级日本三级少妇99| 91av成人在线| 久久久天堂国产精品女人| 中文字幕国产精品| 日韩激情视频在线| 国产成人jvid在线播放| 日韩在线观看你懂的| 欧美日韩999| 欧美一区二区三区四区在线| 91久久国产综合久久91精品网站| 91国内免费在线视频| 成人网在线免费看| 亚洲a在线观看| 亚洲开心激情网| 午夜精品一区二区三区在线播放| 一二美女精品欧洲| 91精品国产777在线观看| 国产精品电影网| 另类专区欧美制服同性| 久久精品免费电影| 综合136福利视频在线| 欧美老少配视频| 高清欧美电影在线| 91精品国产九九九久久久亚洲| 久久久精品欧美| 国产精品亚发布| 欧美日韩国产成人| 欧美激情网站在线观看| 欧美电影在线观看| 日韩欧美中文第一页| 怡红院精品视频| 欧美一区二区视频97| 亚洲第一精品福利| 亚洲欧洲视频在线| 26uuu久久噜噜噜噜| 97久久精品人人澡人人爽缅北| 国产极品精品在线观看| 大桥未久av一区二区三区| 国产噜噜噜噜噜久久久久久久久| 狠狠操狠狠色综合网| 亚洲一区二区中文字幕| 日韩亚洲国产中文字幕| 日韩精品久久久久久福利| 亚洲图片在线综合| 亚洲高清av在线| 欧美麻豆久久久久久中文| 欧美精品日韩www.p站| 亚洲国产成人久久综合一区| 国产精品久久久久aaaa九色| 97婷婷大伊香蕉精品视频| 国产日韩在线亚洲字幕中文| 国产精品日韩欧美大师| 国产aⅴ夜夜欢一区二区三区| 日本久久久久久久久久久| 国产精品三级美女白浆呻吟| 精品自拍视频在线观看| 欧美性猛交xxxx富婆| 91高潮在线观看| 亚洲japanese制服美女| 98精品国产自产在线观看| 亚洲色图欧美制服丝袜另类第一页| 午夜精品理论片| 欧美日韩一区二区在线播放| 国产成人精品综合| 色悠悠国产精品| 欧美成人四级hd版| 亚洲精选在线观看| 一区二区三区 在线观看视| 日韩av电影在线网| 91久久综合亚洲鲁鲁五月天| 国产一区红桃视频| 亚洲午夜女主播在线直播| 91精品视频观看| 久久精品电影一区二区| 欧美精品精品精品精品免费| 日韩欧美国产一区二区| 欧洲成人在线视频| 成人精品aaaa网站| 日韩精品在线观看网站| 久久99精品视频一区97| 欧美激情二区三区| 亚洲精品久久久久久久久久久久久| 中文字幕精品久久久久| 亚洲国产成人av在线| 色综合伊人色综合网| 91久久嫩草影院一区二区| 日韩欧美中文字幕在线播放| 亚洲无限乱码一二三四麻| 日韩视频免费大全中文字幕| 亚洲美女性视频| 国产精品吹潮在线观看| 97超级碰在线看视频免费在线看| 黑人巨大精品欧美一区二区三区| 欧美视频专区一二在线观看| 在线国产精品视频| 日韩av快播网址| 亚洲欧美日韩精品| 国产精品一久久香蕉国产线看观看| 亚洲自拍高清视频网站| 国产视频精品免费播放| 国内精品中文字幕| 成人免费观看49www在线观看| 国产欧美一区二区三区久久| 欧美大奶子在线| 国产亚洲精品美女| 日本中文字幕不卡免费| 亚洲人成在线观看| 91精品啪aⅴ在线观看国产| 永久免费毛片在线播放不卡| 日韩在线观看免费全| 亚洲精品一区二区三区不| 亚洲丁香久久久| 亚洲最大的免费| 亚洲精品国产精品国自产在线| 亚洲欧美在线一区| 91精品国产高清自在线看超| 国产成人av网址| 538国产精品一区二区免费视频| 欧美极品美女视频网站在线观看免费| 国产精品久久久一区| 国产精品美女久久久久av超清| 日本19禁啪啪免费观看www| 亚洲天堂精品在线| 亚洲免费伊人电影在线观看av| 国产精品视频一区二区高潮| 欧美日韩一区二区在线播放| 亚洲国产天堂网精品网站| 成人a在线观看| 九色精品美女在线| 97久久超碰福利国产精品…| 亚洲最大av网| 久久久久久久香蕉网| 亚洲图中文字幕| 伊人久久久久久久久久久久久| 亚洲第一黄色网| 国产亚洲福利一区| 国产在线观看精品| 夜夜嗨av色综合久久久综合网| 国产精品久久久精品| 97视频在线观看免费高清完整版在线观看| 欧美国产高跟鞋裸体秀xxxhd| 成人性生交大片免费看小说| 色999日韩欧美国产| 国产精品一香蕉国产线看观看| 91社影院在线观看| 国产免费一区二区三区香蕉精| 亚洲成色777777女色窝| 亚洲视频第一页| 色妞一区二区三区| 午夜精品理论片| 国产欧美亚洲视频| 中文字幕欧美精品日韩中文字幕| 久久久久久一区二区三区|