回调地狱和Promise
目录
1.回调地狱callback-hell
由于fs.readFile是异步操作,所以你不能判断下面三个文件的执行顺序
var fs = require('fs')fs.readFile('./data/a.txt','utf-8',function(err, data) {if(err) {throw err}console.log(data)
})fs.readFile('./data/b.txt','utf-8',function(err, data) {if(err) {throw err}console.log(data)
})fs.readFile('./data/c.txt','utf-8',function(err, data) {if(err) {throw err}console.log(data)
})
通过回调嵌套的方式可以保证执行顺序
所谓回调嵌套,就是一个异步请求的回调函数中含有另一个异步请求
var fs = require('fs')fs.readFile('./data/a.txt','utf-8',function(err, data) {if(err) {throw err}console.log(data)fs.readFile('./data/b.txt','utf-8',function(err, data) {if(err) {throw err}console.log(data)fs.readFile('./data/c.txt','utf-8',function(err, data) {if(err) {throw err}console.log(data)})})
})
嵌套多了,就成了回调地狱(callback hell),缺点就是代码丑,而且不方便维护
2.Promise
为了解决上面这种回调地狱,ES6语法新增了一个API:Promise
Promise本身是一个容器,里面往往封装一个异步任务
promise有三种状态:Pending、Resolved、Rejected
对上面的例子用Promise改造一下
const 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)})
3.应用场景举例
有时候我们需要拿到多个接口的数据来渲染页面
安装json-server: npm install --g json-server
json-server可以直接把一个json文件托管成一个具备全RESTful风格的API,并支持跨域、jsonp、路由订制、数据快照保存等功能的 web 服务器。
执行命令:json-server --watch data.json(默认端口是3000,也可以自己指定端口)
通过启动json-server服务并侦听data.json,就可以将data.json文件托管成一个 web 服务,此时data.json就充当了数据库服务器的作用。
安装art-template: npm i art-template
demo.html(传统写法)
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title></title></head><body><form id="user_form"></form><script src="node_modules/art-template/lib/template-web.js"></script><script type="text/template" id="tpl"><div><label for="">用户名</label><input type="text" name="" value="{{ user.username }}"></div><div><label for="">年龄</label><input type="text" name="" value="{{ user.age }}"></div><div><label for="">职业</label><select>{{ each jobs }}{{ if user.job === $value.id }}<option selected>{{ $value.name }}</option>{{ else }}<option>{{ $value.name }}</option>{{ /if }}{{ /each }}</select></div></script><script>get('http://127.0.0.1:3000/users/1', function(userData) {get('http://127.0.0.1:3000/jobs', function (jobsData) {var htmlStr = template('tpl', {user: JSON.parse(userData),jobs: JSON.parse(jobsData)})document.querySelector('#user_form').innerHTML = htmlStr}) })function get(url, callback) {var oReq = new XMLHttpRequest()oReq.onload = function() {callback(oReq.responseText)}oReq.open("get", url, true)oReq.send()}</script></body>
</html>
demo.html(使用jQuery,安装jquery:npm i jquery)
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title></title></head><body><form id="user_form"></form><script src="node_modules/art-template/lib/template-web.js"></script><script src="node_modules/jquery/dist/jquery.js"></script><script type="text/template" id="tpl">... // 原代码不变</script><script>var data = {}$.get('http://127.0.0.1:3000/users/1').then(function(usersData) {data.user = usersDatareturn $.get('http://127.0.0.1:3000/jobs')}).then(function(jobsData) {data.jobs = jobsDatavar htmlStr = template('tpl', data)document.querySelector('#user_form').innerHTML = htmlStr})</script></body>
</html>
demo.html(使用Promise封装ajax方法)
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title></title></head><body><form id="user_form"></form><script src="node_modules/art-template/lib/template-web.js"></script><script src="node_modules/jquery/dist/jquery.js"></script><script type="text/template" id="tpl">... //原代码不变</script><script>var data = {}get('http://127.0.0.1:3000/users/1').then(function(usersData) {data.user = usersDatareturn get('http://127.0.0.1:3000/jobs')}).then(function(jobsData) {data.jobs = jobsDatavar 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() {resolve(JSON.parse(oReq.responseText))}oReq.onerror = function(err) {reject(err)}oReq.open("get", url, true)oReq.send()})}</script></body>
</html>
data.json
{"users": [{"id": 1,"username": "admin","age": 18,"job": 3},{"id": 2,"username": "admin2","age": 17,"job": 2},{"id": 3,"username": "admin3","age": 19,"job": 3}],"jobs": [{"id": 1,"name": "学生"},{"id": 2,"name": "教师"},{"id": 3,"name": "医生"},{"id": 4,"name": "程序员"}]
}
4.操作数据库使用Promise
下面是mongoose操作数据库时使用promise的例子
const mongoose = require('mongoose')
var Schema = mongoose.Schemamongoose.connect('mongodb://localhost/test')var userSchema = new Schema({username: {type: String,required: true},password: {type: String,required: true},email: {type: String}
})var User = mongoose.model('User', userSchema)// 注册用户
User.findOne({username: 'zs'
}).then(function(user) {if(user) {console.log('用户已存在')} else {return new User({username: 'zs',password: '123456',email: 'admin@admin.com'})}}).catch()
回调地狱和Promise相关推荐
- 【JavaScript】回调地狱、Promise
文章目录 1. 回调函数 2. 异步任务 3. 回调地狱 4. Promise 4.1 Promise定义 4.2 Promise基础用法 4.2.1 生成Promise实例 4.2.2 Promis ...
- 详解回调地狱以及promise
1.什么是回调地狱? 说promise之前必须先简单说下,回调地狱 回调地狱:在回调函数中又嵌套了多层回调函数,便会形成回调地狱 JS中或node中,都大量的使用了回调函数进行异步操作,而异步操作什么 ...
- ES6(三)——回调地狱和promise异步任务顺序执行(传参、错误处理)
文章目录 方法一.回调函数(回调地狱) 方法二:promise 2.1异步任务传参(单个) 2.2异步任务传参(多个) 2.3 错误处理 2.4 Promiss对象三大状态: (学名) 2.5 Pro ...
- 回调地狱终结者——Promise
在Web前端开发中,我们使用JavaScript会大量依赖异步计算.比如说,Ajax请求时,我们可能会需要不只一个请求来达到某种目的,此时需要后面的请求依赖于前面请求的结果.这种情况在简单的业务中并无 ...
- 回调地狱与promise
<script src="js/ajax.js"></script><script>// function fn(a){// a()// }// ...
- 什么是回调地狱以及promise的链式调用和aysnc/await
上面一篇博客写到了回调地域的问题,这篇博客将深究这个词语,如下例: doSomething(function(result){doSomethingElse(result, function(newR ...
- 【Callback Hell】一文让你轻松了解何为回调地狱?
回调地狱[Callback Hell] 前提知识点: 单线程和异步: JS是单线程语言,只能同时做一件事儿 (例子:做一个ajax请求去加载资源,或者说弄一个定时器,先等待1秒钟后干嘛,如果按照单线程 ...
- 一文告诉你什么是回调地狱,如何解决回调地狱?
文章目录 前言 一.回调地狱是什么? 二.如何解决回调地狱 1.Promise 2.async/await 总结 前言 在正式了解"回调地狱"之前,我们先了解两个概念: 回调函数 ...
- 使用ES6的Promise完美解决回调地狱
相信经常使用ajax的前端小伙伴,都会遇到这样的困境:一个接口的参数会需要使用另一个接口获取. 年轻的前端可能会用同步去解决(笑~),因为我也这么干过,但是极度影响性能和用户体验. 正常的前端会把接口 ...
最新文章
- oc 协议 回调 静态成员_OC底层原理探究:Category、关联对象和block本质
- Spring中ClassPathXmlApplicationContext类的简单使用
- thinkphp几个表的数据合并,并用数组分页
- 洛谷P2835 刻录光盘
- wxWidgets:调试
- sklearn自学指南(part19)--LDA和QDA
- 如何用Python画一个中国地图?
- 阿里云视频云「 vPaaS 」演绎了怎样的音视频应用开发「未来图景」
- MediaRecorder录像怎么旋转呀?
- 原生JS那些事:原生JS添加和删除class类名
- Windows 使用浮动键盘语言栏
- c#位图转换未矢量图_PS基础:像素与分辨率,位图与矢量图
- 毕设题目:Matlab回归预测
- 基于灰狼优化算法的线性规划问题求解matlab程序
- Robo 3T显示MongoDB数据时区晚8小时问题
- filesplit的Python项目详细描述
- 有监督学习、无监督学习和半监督学习之间的区别
- 博客整理——K米测评
- java mp3合并_java合并MP3文件
- Java基础--继承