目录

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相关推荐

  1. 【JavaScript】回调地狱、Promise

    文章目录 1. 回调函数 2. 异步任务 3. 回调地狱 4. Promise 4.1 Promise定义 4.2 Promise基础用法 4.2.1 生成Promise实例 4.2.2 Promis ...

  2. 详解回调地狱以及promise

    1.什么是回调地狱? 说promise之前必须先简单说下,回调地狱 回调地狱:在回调函数中又嵌套了多层回调函数,便会形成回调地狱 JS中或node中,都大量的使用了回调函数进行异步操作,而异步操作什么 ...

  3. ES6(三)——回调地狱和promise异步任务顺序执行(传参、错误处理)

    文章目录 方法一.回调函数(回调地狱) 方法二:promise 2.1异步任务传参(单个) 2.2异步任务传参(多个) 2.3 错误处理 2.4 Promiss对象三大状态: (学名) 2.5 Pro ...

  4. 回调地狱终结者——Promise

    在Web前端开发中,我们使用JavaScript会大量依赖异步计算.比如说,Ajax请求时,我们可能会需要不只一个请求来达到某种目的,此时需要后面的请求依赖于前面请求的结果.这种情况在简单的业务中并无 ...

  5. 回调地狱与promise

    <script src="js/ajax.js"></script><script>// function fn(a){// a()// }// ...

  6. 什么是回调地狱以及promise的链式调用和aysnc/await

    上面一篇博客写到了回调地域的问题,这篇博客将深究这个词语,如下例: doSomething(function(result){doSomethingElse(result, function(newR ...

  7. 【Callback Hell】一文让你轻松了解何为回调地狱?

    回调地狱[Callback Hell] 前提知识点: 单线程和异步: JS是单线程语言,只能同时做一件事儿 (例子:做一个ajax请求去加载资源,或者说弄一个定时器,先等待1秒钟后干嘛,如果按照单线程 ...

  8. 一文告诉你什么是回调地狱,如何解决回调地狱?

    文章目录 前言 一.回调地狱是什么? 二.如何解决回调地狱 1.Promise 2.async/await 总结 前言 在正式了解"回调地狱"之前,我们先了解两个概念: 回调函数 ...

  9. 使用ES6的Promise完美解决回调地狱

    相信经常使用ajax的前端小伙伴,都会遇到这样的困境:一个接口的参数会需要使用另一个接口获取. 年轻的前端可能会用同步去解决(笑~),因为我也这么干过,但是极度影响性能和用户体验. 正常的前端会把接口 ...

最新文章

  1. oc 协议 回调 静态成员_OC底层原理探究:Category、关联对象和block本质
  2. Spring中ClassPathXmlApplicationContext类的简单使用
  3. thinkphp几个表的数据合并,并用数组分页
  4. 洛谷P2835 刻录光盘
  5. wxWidgets:调试
  6. sklearn自学指南(part19)--LDA和QDA
  7. 如何用Python画一个中国地图?
  8. 阿里云视频云「 vPaaS 」演绎了怎样的音视频应用开发「未来图景」
  9. MediaRecorder录像怎么旋转呀?
  10. 原生JS那些事:原生JS添加和删除class类名
  11. Windows 使用浮动键盘语言栏
  12. c#位图转换未矢量图_PS基础:像素与分辨率,位图与矢量图
  13. 毕设题目:Matlab回归预测
  14. 基于灰狼优化算法的线性规划问题求解matlab程序
  15. Robo 3T显示MongoDB数据时区晚8小时问题
  16. filesplit的Python项目详细描述
  17. 有监督学习、无监督学习和半监督学习之间的区别
  18. 博客整理——K米测评
  19. java mp3合并_java合并MP3文件
  20. Java基础--继承

热门文章

  1. python pyc文件解析_pyc文件
  2. 超越・蝶变・升华 | 联诚发召开2020年度述职暨表彰大会
  3. iperf测带宽使用方法
  4. 苹果电脑mac系统安装TA-lib安装成功了
  5. 使用overlay挂载squashfs
  6. java实现画图,可更换图形的各种形状,颜色,可擦除
  7. 字符流和字节流的区别和使用
  8. 2022 年全球10大最佳自动化测试工具
  9. http 与 https 的区别以及加密详解
  10. Jenkins 自动部署VUE项目