国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 語言 > JavaScript > 正文

淺談Node.js之異步流控制

2024-05-06 15:25:16
字體:
來源:轉載
供稿:網友

前言

在沒有深度使用函數回調的經驗的時候,去看這些內容還是有一點吃力的。由于Node.js獨特的異步特性,才出現了“回調地獄”的問題,這篇文章中,我比較詳細的記錄了如何解決異步流問題。

文章會很長,而且這篇是對異步流模式的解釋。文中會使用一個簡單的網絡蜘蛛的例子,它的作用是抓取指定URL的網頁內容并保存在項目中,在文章的最后,可以找到整篇文章中的源碼demo。

1.原生JavaScript模式

本篇不針對初學者,因此會省略掉大部分的基礎內容的講解:

(spider_v1.js)

const request = require("request");const fs = require("fs");const mkdirp = require("mkdirp");const path = require("path");const utilities = require("./utilities");function spider(url, callback) {  const filename = utilities.urlToFilename(url);  console.log(`filename: ${filename}`);  fs.exists(filename, exists => {    if (!exists) {      console.log(`Downloading ${url}`);      request(url, (err, response, body) => {        if (err) {          callback(err);        } else {          mkdirp(path.dirname(filename), err => {            if (err) {              callback(err);            } else {              fs.writeFile(filename, body, err => {                if (err) {                  callback(err);                } else {                  callback(null, filename, true);                }              });            }          });        }      });    } else {      callback(null, filename, false);    }  });}spider(process.argv[2], (err, filename, downloaded) => {  if (err) {    console.log(err);  } else if (downloaded) {    console.log(`Completed the download of ${filename}`);  } else {    console.log(`${filename} was already downloaded`);  }});

上邊的代碼的流程大概是這樣的:

    把url轉換成filename 判斷該文件名是否存在,若存在直接返回,否則進入下一步 發請求,獲取body 把body寫入到文件中

這是一個非常簡單版本的蜘蛛,他只能抓取一個url的內容,看到上邊的回調多么令人頭疼。那么我們開始進行優化。

首先,if else 這種方式可以進行優化,這個很簡單,不用多說,放一個對比效果:

/// beforeif (err) {  callback(err);} else {  callback(null, filename, true);}/// afterif (err) {  return callback(err);}callback(null, filename, true);

代碼這么寫,嵌套就會少一層,但經驗豐富的程序員會認為,這樣寫過重強調了error,我們編程的重點應該放在處理正確的數據上,在可讀性上也存在這樣的要求。

另一個優化是函數拆分,上邊代碼中的spider函數中,可以把下載文件和保存文件拆分出去。

(spider_v2.js)

const request = require("request");const fs = require("fs");const mkdirp = require("mkdirp");const path = require("path");const utilities = require("./utilities");function saveFile(filename, contents, callback) {  mkdirp(path.dirname(filename), err => {    if (err) {      return callback(err);    }    fs.writeFile(filename, contents, callback);  });}function download(url, filename, callback) {  console.log(`Downloading ${url}`);  request(url, (err, response, body) => {    if (err) {      return callback(err);    }    saveFile(filename, body, err => {      if (err) {        return callback(err);      }      console.log(`Downloaded and saved: ${url}`);      callback(null, body);    });  })}function spider(url, callback) {  const filename = utilities.urlToFilename(url);  console.log(`filename: ${filename}`);  fs.exists(filename, exists => {    if (exists) {      return callback(null, filename, false);    }    download(url, filename, err => {      if (err) {        return callback(err);      }      callback(null, filename, true);    })  });}spider(process.argv[2], (err, filename, downloaded) => {  if (err) {    console.log(err);  } else if (downloaded) {    console.log(`Completed the download of ${filename}`);  } else {    console.log(`${filename} was already downloaded`);  }});            
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

主站蜘蛛池模板: 响水县| 康乐县| 贵溪市| 大荔县| 彭泽县| 迁安市| 黔江区| 新绛县| 宁化县| 新蔡县| 中方县| 衡阳县| 合川市| 井研县| 慈利县| 巨野县| 卢湾区| 贵德县| 左贡县| 昌邑市| 陕西省| 临清市| 渭源县| 黄冈市| 德惠市| 临沭县| 达州市| 龙里县| 太保市| 敖汉旗| 丰镇市| 丰原市| 武强县| 云南省| 调兵山市| 鄯善县| 邮箱| 沙河市| 穆棱市| 龙口市| 乌海市|