node.js养成计划(七)异步执行、回调函数、promise、await、async

3 篇文章 0 订阅

一、异步与callback回调函数

  • js/jquery的ajax就是异步的
  • axios也是异步的
  • 在node.js中fs 模块库操作文件的方法都是异步的
  • setTimeout是异步

如果需要得到异步函数的操作结果,必须通过回调函数来获取.

1.那我们怎么获取文件的内容呢?

通过回调函数callback来获取
回调函数就是为了获取异步结果而生

function fn(callback){
	setTimeout(function () {
		var data = 123;
		callback(123);
	},1000)
}
// 调用结果
// 如果需要获取一个函数中异步操作的结果,则必须通过回调函数来获取
fn(function (data) {
  console.log(data)
})

获取nodejs fs 读取文件的内容

function fileContent (callback) {
  fs.readFile(dbPath, 'utf8', function (err, data) {
    if (err) {
      return callback(err)
    }
    callback(null, JSON.parse(data).students)
  })
}
// 调用
fileContent(function (err, students) {
  	console.log(students);
 })
2.封装ajax
get请求
function get(url,callback) {
	var xhr = new XMLHTTPRequest();
	xhr.onload = function () {
		// 回调函数
		console.log(xhr.responseText)
		callback(xhr.responseText);
	};
	xhr.open("get", "请求路径", true)
	xhr.send();
}

调用
----------------------------------------
get("/getinfo", function(data) {
	console.log(data)
})

二、promise解决回调地狱(callback hell)层层镶套的异步调用

1.模拟回调地狱,通过镶套的方式保证执行顺序
var fs = require('fs')

fs.readFile('./data/a.txt', 'utf8', function (err, data) {
  if (err) {
    // return console.log('读取失败')
    // 抛出异常
    //    1. 阻止程序的执行
    //    2. 把错误消息打印到控制台
    throw err
  }
  console.log(data)
  fs.readFile('./data/b.txt', 'utf8', function (err, data) {
    if (err) {
      throw err
    }
    console.log(data)
    fs.readFile('./data/c.txt', 'utf8', function (err, data) {
      if (err) {
        throw err
      }
      console.log(data)
    })
  })
})

2.Promise 为了解决回调地狱而生,ES6新增
2.1 Promise语法 API
  • Promise是一个构造函数,创建promise容器,存放一个异步任务
2.1.1 下面的案例Promise容器一旦创建,立即执行里面的代码,但未必就先执行完
new Promise(function () {
	fs.readFile('./data/a.txt', 'utf8', function(err, data){
		if(err) {
			// 失败了,承诺容器中的任务失败了输出数据
			console.log(err)
		}else{
			console。log(data)
		}
	})
})
2.1.2 Promise 管理异步

在这里插入图片描述
pending:等待状态,比如正在进行网络请求,或者定时器没有到时间。
**fulfill:**满足状态,当我们主动回调了resolve时,就处于该状态,并且会回调.then()
reject:拒绝状态,当我们主动回调了reject时,就处于该状态,并且会回调.catch()

  • Promise API初识
var p1 = new Promise(function (resolve, reject) {
	fs.readFile('./data/a.txt', 'utf8', function(err, data){
		if(err) {
			// 失败了,承诺容器中的任务失败了输出数据
			// 把容器的Pending状态变为Rejected
			reject(err)
		}else{
			// 把容器的Pending状态变为Resolved
			resolve(data)
		}
	})
})

执行承诺

p1.then(function(data){
	console.log(data)
}.function(err){
	console.log("读取文件失败" + err)
})
--------也可以写成这样--------------

p1.then((data) => {
	console.log(data)
}).catch((error) => {
	console.log(error)
})

在这里插入图片描述

  • Promise 链式调用
var fs = require('fs')

var p1 = new Promise(function (resolve, reject) {
  fs.readFile('./data/a.txt', 'utf8', function (err, data) {
    if (err) {
      reject(err)
    } else {
      resolve(data)
    }
  })
})

var p2 = new Promise(function (resolve, reject) {
  fs.readFile('./data/b.txt', 'utf8', function (err, data) {
    if (err) {
      reject(err)
    } else {
      resolve(data)
    }
  })
})

var p3 = new Promise(function (resolve, reject) {
  fs.readFile('./data/c.txt', 'utf8', function (err, data) {
    if (err) {
      reject(err)
    } else {
      resolve(data)
    }
  })
})

d调用

p1
  .then(function (data) {
    console.log(data)
    // 当 p1 读取成功的时候
    // 当前函数中 return 的结果就可以在后面的 then 中 function 接收到
    // 当你 return 123 后面就接收到 123;没有 return 后面收到的就是 undefined
  // 上面那些 return 的数据没什么卵用
    // 真正有用的是:我们可以 return 一个 Promise 对象
    // 当 return 一个 Promise 对象的时候,后续的 then 中的 方法的第一个参数会作为 p2 的 resolve
    return p2
  }, function (err) {
    console.log('读取文件失败了', err)
  })
  .then(function (data) {
    console.log(data)
    return p3
  })
  .then(function (data) {
    console.log(data)
    console.log('end')
  })

在这里插入图片描述

2.1.3 优化文件读取回调地狱问题
var fs = require('fs')

function pReadFile(filePath) {
  return new Promise(function (resolve, reject) {
    fs.readFile(filePath, 'utf8', function (err, data) {
      if (err) {
        reject(err)
      } else {
        resolve(data)
      }
    })
  })
}

调用

pReadFile('./data/a.txt')
  .then(function (data) {
    console.log(data)
    return pReadFile('./data/b.txt')
  })
  .then(function (data) {
    console.log(data)
    return pReadFile('./data/c.txt')
  })
  .then(function (data) {
    console.log(data)
  })

三、Promise封装ajax

pGet('http://127.0.0.1:3000/user').then(function (data) {
  console.log(data)
})
function pGet(url, callback) {
  return new Promise(function (r
    var oReq = new XMLHttpReques
    // 当请求加载成功之后要调用指定的函数
    oReq.onload = function () {
      // 我现在需要得到这里的 oReq.respons
      callback && callback(JSON.
      resolve(JSON.parse(oReq.re
    }
    oReq.onerror = function (err
      reject(err)
    }
    oReq.open("get", url, true)
    oReq.send()
  })
}
// 这个 get 是 callback 方式的 API
// 可以使用 Promise 来解决这个问题
/*function get(url, callback) {
  var oReq = new XMLHttpRequest(
  // 当请求加载成功之后要调用指定的函数
  oReq.onload = function () {
    // 我现在需要得到这里的 oReq.responseT
    callback(oReq.responseText)
  }
  oReq.open("get", url, true)
  oReq.send()
}*/

四、 await | asyns

  • asyns 作用在调用异步方法的方法上,使他变成同步方法

  • await 作用于promise

  • 两者共同配配合,等待拿到一步方法的返回值

async function test() {
	await 发送请求 promise 对象
	await 发送请求
}

五、mongoose 中的方法都是Promise封装的

如:

User.find(function (err, ret) {
  if (err) {
    console.log('查询失败')
  } else {
    console.log(ret)
  }
})

就可以写成

var User = mongoose.model('User', userSchema)
User.find().then(function (data) {
  console.log(data)
})

只要出现了异步镶套,我们就可以使用Promiss来规范,来then

六、Promise.all执行多个异步任务

会等待包含的所有异步任务完成,返回结果是个异步任务执行结果的集合;

Promise.all([
	new Promise((resolve, reject) => {
		$ajax({
			url: "url1",
			success: function (data) {
				resolve(data)
			}
		})
	}),
	
	new Promise((resolve, reject) => {
		$ajax({
			url: "url2",
			success: function (data) {
				resolve(data)
			}
		})
	})
]).then(result=>{
	// 分别对应两个请求的回调函数
	console.log(result[0])
	console.log(result[1])
})
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值