Promise学习——解决回调地狱问题

Promise

promise 容器概念:

在这里插入图片描述

callback hell(回调地狱):
在这里插入图片描述

文件的读取无法判断执行顺序(文件的执行顺序是依据文件的大小来决定的)(异步api无法保证文件的执行顺序)

var fs = require('fs');

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

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

通过回调嵌套的方式来保证顺序:

var fs = require('fs');

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

为了解决以上编码方式带来的问题(回调地狱嵌套),所以在EcmaScript6新增了一个API:Promise

  • Promise:承诺,保证
  • Promise本身不是异步的,但往往都是内部封装一个异步任务

基本语法:

var fs = require('fs')
// 在EcmaScript 6 中新增了一个API Promise
// Promise 是一个构造函数


// 创建 Promise 容器
// 1.给别人一个承诺 I promise you
//		Promise 容器一旦创建,就开始执行里面的代码
var p1 = new Promise(function(resolve, reject) {
    
    
	fs.readFile('./data/a.txt', 'utf-8', function(err, data) {
    
    
		if (err) {
    
    
			// 失败了,承诺容器中的任务失败了
			// console.log(err)
			// 把容器的Pending状态变为Rejected
			// 调用的reject方法实际上就是then方法传递的第二个参数函数function
			reject(err)
		} else {
    
    
			// 承诺容器中的任务成功了
			// console.log(data)
			// 把容器的Pending状态变为成功
			// 也就是说这里调用的resolve方法实际上就是then方法传递的第一个function
			resolve(data)
		}
	})
})


// p1 就是那个承诺
// 当 p1 成功了,然后(then)做指定的操作
// then 方法接收的function就是容器中的resolve函数
p1.then(function(data) {
    
    
	console.log(data)
}, function(err) {
    
    
	console.log('读取文件失败', err)
})

在这里插入图片描述

链式循环:

封装Promise的readFile

var fs = require('fs')



function pReadFile(filePath) {
    
    
	return new Promise(function(resolve, reject) {
    
    
		fs.readFile(filePath, 'utf-8', 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)
	})


在这里插入图片描述

var fs = require('fs')
// 在EcmaScript 6 中新增了一个API Promise
// Promise 是一个构造函数


// 创建 Promise 容器
// 1.给别人一个承诺 I promise you
//		Promise 容器一旦创建,就开始执行里面的代码
var p1 = new Promise(function(resolve, reject) {
    
    
	fs.readFile('./data/a.txt', 'utf-8', function(err, data) {
    
    
		if (err) {
    
    
			// 失败了,承诺容器中的任务失败了
			// console.log(err)
			// 把容器的Pending状态变为Rejected
			// 调用的reject方法实际上就是then方法传递的第二个参数函数function
			reject(err)
		} else {
    
    
			// 承诺容器中的任务成功了
			// console.log(data)
			// 把容器的Pending状态变为成功
			// 也就是说这里调用的resolve方法实际上就是then方法传递的第一个function
			resolve(data)
		}
	})
})


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

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


// p1 就是那个承诺
// 当 p1 成功了,然后(then)做指定的操作
// then 方法接收的function就是容器中的resolve函数
p1.then(function(data) {
    
    
	console.log(data)
	// 当 p1读取成功的时候
	// 当前函数中 return 的结果就可以在后面的 then中function接收到
	// 当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)
})

在这里插入图片描述

需求:分别向两个接口:users和jobs发送请求,获取响应数据,将数据通过art-template 模板渲染到html页面上

第一种:使用自己封装的callback方式

在这里插入图片描述

data.json:

{
    
    
	"users": [{
    
    
			"id": 1,
			"username": "admin",
			"age": 22,
			"job": 4
		},
		{
    
    
			"id": 2,
			"username": "admin2",
			"age": 18,
			"job": 1
		},
		{
    
    
			"id": 3,
			"username": "admin3",
			"age": 18,
			"job": 1
		}
	],
	"jobs": [{
    
    
			"id": 1,
			"name": "学生"
		},
		{
    
    
			"id": 2,
			"name": "老师"
		},
		{
    
    
			"id": 3,
			"name": "司机"
		},
		{
    
    
			"id": 4,
			"name": "演员"
		},
		{
    
    
			"id": 5,
			"name": "画家"
		},
		{
    
    
			"id": 6,
			"name": "电竞人"
		}
	]
}

这里使用json-server来开启一个服务:
首先,安装 json-server: npm install -g json-server
在这里插入图片描述
然后通过命令:json-server --watch data.json启动服务:
在这里插入图片描述
在这里插入图片描述
由于用到了模板引擎来将数据渲染到页面上,所以需要再安装一个art-template包:
npm i art-template
在这里插入图片描述

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<form action="#" id="user_form">

		</form>

		<script type="text/text/template" id="tpl">
			<label for="">用户名</label>
				<input type="text" value="{
     
     { user.username }}">
				<label for="">年龄</label>
				<input type="text" value="{
     
     { user.age }}">
				<label for="">职业</label>
				<select name="" id="">
					{
     
     {
     
      each jobs }}
						{
     
     {
     
      if user.job === $value.id }}
							<option value="{
     
     { $value.id }}" selected="selected">{
     
     {
     
      $value.name }}</option>
						{
     
     {
     
      else }}
							<option value="{
     
     { $value.id }}">{
     
     {
     
      $value.name }}</option>
						{
     
     {
     
      /if }}		
					{
     
     {
     
      /each }}
				</select>						
		</script>

		<script src="node_modules/art-template/lib/template-web.js"></script>
		<script>
			// 用户表
			// 		其中一个接口获取用户数据
			//      职业:1
			// 职业信息表
			//  	其中一个接口获取所有的职业信息
			get('http://127.0.0.1:3000/users/1', function(userData) {
     
     
				// data = JSON.parse(data)

				get('http://127.0.0.1:3000/jobs', function(jobsData) {
     
     
					// console.log(userData, jobsData)
					var htmlStr = template('tpl', {
     
     
						user: JSON.parse(userData),
						jobs: JSON.parse(jobsData)
					})
					console.log(htmlStr)
					document.querySelector('#user_form').innerHTML = htmlStr
				})
			})


			function get(url, callback) {
     
     
				var oReq = new XMLHttpRequest()
				// 当请求加载成功之后要调用指定的函数
				oReq.onload = function() {
     
     
					// 我现在需要得到这里的 oReq.responseText
					callback(oReq.responseText)
				}
				oReq.open("get", url, true)
				oReq.send()
			}
		</script>
	</body>
</html>

在这里插入图片描述

第二种:使用jquery的promise方式

在这里插入图片描述

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<form action="#" id="user_form">

		</form>

		<script type="text/text/template" id="tpl">
			<label for="">用户名</label>
				<input type="text" value="{
    
    { user.username }}">
				<label for="">年龄</label>
				<input type="text" value="{
    
    { user.age }}">
				<label for="">职业</label>
				<select name="" id="">
					{
    
    {
    
     each jobs }}
						{
    
    {
    
     if user.job === $value.id }}
							<option value="{
    
    { $value.id }}" selected="selected">{
    
    {
    
     $value.name }}</option>
						{
    
    {
    
     else }}
							<option value="{
    
    { $value.id }}">{
    
    {
    
     $value.name }}</option>
						{
    
    {
    
     /if }}		
					{
    
    {
    
     /each }}
				</select>						
		</script>

		<script src="node_modules/jquery/dist/jquery.js"></script>
		<script src="node_modules/art-template/lib/template-web.js"></script>
		<script>
			// 用户表
			// 		其中一个接口获取用户数据
			//      职业:1
			// 职业信息表
			//  	其中一个接口获取所有的职业信息
			/* get('http://127.0.0.1:3000/users/1', function(userData) {
				// data = JSON.parse(data)

				get('http://127.0.0.1:3000/jobs', function(jobsData) {
					// console.log(userData, jobsData)
					var htmlStr = template('tpl', {
						user: JSON.parse(userData),
						jobs: JSON.parse(jobsData)
					})
					console.log(htmlStr)
					document.querySelector('#user_form').innerHTML = htmlStr
				})
			}) */

			var data = {
    
    }
			$.get('http://127.0.0.1:3000/users/1')
				.then(function(userData) {
    
    
					console.log(userData)
					data.user = userData
					return $.get('http://127.0.0.1:3000/jobs')
				})
				.then(function(jobsData) {
    
    
					console.log(jobsData)
					data.jobs = jobsData
					console.log(data)
					var htmlStr = template('tpl', data)
					console.log(htmlStr)
					document.querySelector('#user_form').innerHTML = htmlStr

				})




			function get(url, callback) {
    
    
				var oReq = new XMLHttpRequest()
				// 当请求加载成功之后要调用指定的函数
				oReq.onload = function() {
    
    
					// 我现在需要得到这里的 oReq.responseText
					callback(oReq.responseText)
				}
				oReq.open("get", url, true)
				oReq.send()
			}
		</script>
	</body>
</html>

在这里插入图片描述

3.用promise封装ajax版:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<form action="#" id="user_form">

		</form>

		<script type="text/text/template" id="tpl">
			<label for="">用户名</label>
				<input type="text" value="{
     
     { user.username }}">
				<label for="">年龄</label>
				<input type="text" value="{
     
     { user.age }}">
				<label for="">职业</label>
				<select name="" id="">
					{
     
     {
     
      each jobs }}
						{
     
     {
     
      if user.job === $value.id }}
							<option value="{
     
     { $value.id }}" selected="selected">{
     
     {
     
      $value.name }}</option>
						{
     
     {
     
      else }}
							<option value="{
     
     { $value.id }}">{
     
     {
     
      $value.name }}</option>
						{
     
     {
     
      /if }}		
					{
     
     {
     
      /each }}
				</select>						
		</script>

		<script src="node_modules/jquery/dist/jquery.js"></script>
		<script src="node_modules/art-template/lib/template-web.js"></script>
		<script>
			// 用户表
			// 		其中一个接口获取用户数据
			//      职业:1
			// 职业信息表
			//  	其中一个接口获取所有的职业信息
			/* get('http://127.0.0.1:3000/users/1', function(userData) {
				// data = JSON.parse(data)

				get('http://127.0.0.1:3000/jobs', function(jobsData) {
					// console.log(userData, jobsData)
					var htmlStr = template('tpl', {
						user: JSON.parse(userData),
						jobs: JSON.parse(jobsData)
					})
					console.log(htmlStr)
					document.querySelector('#user_form').innerHTML = htmlStr
				})
			}) */
/* 
			var data = {}
			$.get('http://127.0.0.1:3000/users/1')
				.then(function(userData) {
					console.log(userData)
					data.user = userData
					return $.get('http://127.0.0.1:3000/jobs')
				})
				.then(function(jobsData) {
					console.log(jobsData)
					data.jobs = jobsData
					console.log(data)
					var htmlStr = template('tpl', data)
					console.log(htmlStr)
					document.querySelector('#user_form').innerHTML = htmlStr

				}) */
			var data = {
     
     }
			get('http://127.0.0.1:3000/users/1')
			.then(function(userData) {
     
     
				data.user = userData
				return $.get('http://127.0.0.1:3000/jobs')
			})
			.then(function(jobsData) {
     
     
				data.jobs = jobsData
				var htmlStr = template('tpl', data)
				document.querySelector('#user_form').innerHTML = htmlStr			
			}) 

			function get(url) {
     
     
				return new Promise(function(resolve, reject) {
     
     
					var oReq = new XMLHttpRequest()
					// 当请求加载成功之后要调用指定的函数
					oReq.onload = function() {
     
     
						// 我现在需要得到这里的 oReq.responseText
						resolve(JSON.parse(oReq.responseText))
					}			
					oReq.onerror = function (err) {
     
     
						reject(err)
					}
					oReq.open("get", url, true)
					oReq.send()
				})
			}
			/* function get(url, callback) {
				var oReq = new XMLHttpRequest()
				// 当请求加载成功之后要调用指定的函数
				oReq.onload = function() {
					// 我现在需要得到这里的 oReq.responseText
					callback(oReq.responseText)
				}
				oReq.open("get", url, true)
				oReq.send()
			} */
		</script>
	</body>
</html>

在这里插入图片描述

mongoose所有的API都支持Promise:

// 查询所有
User.find()
	.then(function(data){
    
    
        console.log(data)
    })

注册:

User.findOne({
    
    username:'admin'},function(user){
    
    
    if(user){
    
    
        console.log('用户已存在')
    } else {
    
    
        new User({
    
    
             username:'aaa',
             password:'123',
             email:'fffff'
        }).save(function(){
    
    
            console.log('注册成功');
        })
    }
})
User.findOne({
    
    
    username:'admin'
})
    .then(function(user){
    
    
        if(user){
    
    
            // 用户已经存在不能注册
            console.log('用户已存在');
        }
        else{
    
    
            // 用户不存在可以注册
            return new User({
    
    
                username:'aaa',
                password:'123',
                email:'fffff'
            }).save();
        }
    })
    .then(funciton(ret){
    
    
		console.log('注册成功');
    })

Generator

async函数

猜你喜欢

转载自blog.csdn.net/weixin_44827418/article/details/115347964
今日推荐