1.什么是回调地狱?

说promise之前必须先简单说下,回调地狱
回调地狱:在回调函数中又嵌套了多层回调函数,便会形成回调地狱
JS中或node中,都大量的使用了回调函数进行异步操作,而异步操作什么时候返回结果是不可控的,如果我们希望几个异步请求按照顺序来执行,那么就需要将这些异步操作嵌套起来,嵌套的层数特别多,就会形成回调地狱 或者叫做 横向金字塔。

例如我们创建一个文件夹,里面各自包含一句诗,要求这四个异步按顺序排列

如此大量使用回调函数,便会形成回调地狱

//第一步先导入fs模块
import { readFile } from 'fs'
readFile('./poetry/a.txt', 'utf-8', (err, data) => {console.log(data)readFile('./poetry/b.txt', 'utf-8', (err, data) => {console.log(data)readFile('./poetry/c.txt', 'utf-8', (err, data) => {console.log(data)readFile('./poetry/d.txt', 'utf-8', (err, data) => {console.log(data)})})})
})


为了解决回调地狱带来,代码难于维护和修改的弊端,ES6推出Promise对象来解决回调地狱

2.promise的基本概念

Promise对象是一个构造函数,用来生成Promise实例。是一种异步编程的解决方案,可以替换掉传统的回调函数解决方案。
类似一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。
从语法上说,Promise 是一个对象,使用的时候需要 new
而Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。
实例中,它里面的异步操作就相当于一个承诺,而承诺就会有两种结果,要么完成了承诺的内容,要么失败。
Promise有 resolve(完成) 和 reject(失败) 两个形参
必须传入一个函数作为Promise的参数,这个函数在 new Promise的时候就会执行
将异步任务成功的结果传给 resolve 函数;将失败的信息传给 reject 函数

3.promise的基本用法(青铜)

//第一步先导入fs模块
import { readFile } from 'fs'
//第二步创建promise对象
const p1 = new Promise((resolve, reject) => {readFile('./poetry/a.txt', 'utf-8', (err, data) => {resolve(data)   //暂不做判断,不考虑错误情况})
})
const p2 = new Promise((resolve, reject) => {readFile('./poetry/b.txt', 'utf-8', (err, data) => {resolve(data)   //暂不做判断,不考虑错误情况})
})
const p3 = new Promise((resolve, reject) => {readFile('./poetry/c.txt', 'utf-8', (err, data) => {resolve(data)   //暂不做判断,不考虑错误情况})
})
const p4 = new Promise((resolve, reject) => {readFile('./poetry/d.txt', 'utf-8', (err, data) => {resolve(data)   //暂不做判断,不考虑错误情况})
})
//第三步读取文件
const a = p1.then(res => {console.log(res);      //3.1 then()中的回调函数,不写返回值,默认返回一个空白的Promise对象,//3.2如果返回一个真实的Promise对象,那么就会赋值给 then()return p2               // 3.3返回一个 Promise 对象,调用下一个 then();
})
const b = a.then(res => {console.log(res);return p3
})
const c = b.then(res => {console.log(res);return p4
})
const d = c.then(res => {console.log(res)
})

4.promise的封装(黄金)

Promise 实例具有then方法,then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法。
采用链式的then,可以指定一组按照次序调用的回调函数。这时,前一个回调函数,有可能返回的还是一个Promise对象(即有异步操作),这时后一个回调函数,就会等待该Promise对象的状态发生变化,才会被调用。

//第一步导入fs模块
import { readFile } from 'fs'
//第二步封装一个方法.返回一个promise对象
function getpromise(url) {return new Promise((resolve, reject) => {readFile(url, 'utf-8', (err, data) => {resolve(data)  //暂不做判断,不考虑错误情况})})
}
//调用
getpromise('./poetry/a.txt').then(res => {console.log(res);return getpromise('./poetry/b.txt')
}).then(res => {console.log(res);return getpromise('./poetry/c.txt')
}).then(res => {console.log(res);return getpromise('./poetry/d.txt')
}).then(res => console.log(res))

注意:then方法接收一个函数类型的参数,只处理成功
then方法接收两个函数类型的参数,分别用于接收 resolve 的值 和 reject 的值
then方法也可以只接收一个参数,表示只接收 resolve 的值,失败的结果可以通过链式调用catch方法捕获

5.promise的模块(钻石)

//需要先下载模块: npm  i   then-fs
// // 普通fs模块,readFile()返回 undefined ;
// // then-fs模块,readFile()返回 Promise 对象;
//先导入then-fs模块
import thenFs from 'then-fs'
// 读取文件
thenFs.readFile('./poetry/a.txt', 'utf8').then(res => {console.log(res);return thenFs.readFile('./poetry/b.txt', 'utf8');
}).then(res => {console.log(res);return thenFs.readFile('./poetry/c.txt', 'utf8');
}).then(res => {console.log(res);return thenFs.readFile('./poetry/d.txt', 'utf8');
}).then(res => console.log(res))

5.1Promise中的同步异步

Promise被创建的时候,执行的是同步代码;
new Promise 和 new 其他对象一样,是同步任务。
但是获取结果时(调用 resolve 触发 then方法时)是异步的。
// then()和catch()里面执行的是异步代码;

6.promise进阶(星耀)

ES2017 标准引入了 async 和 await,使得异步操作变得更加方便。

6.1 async函数

async 函数是什么?一句话,它就是 Generator 函数的语法糖。
async 用于修饰一个 function
async 修饰的函数,总是返回一个 Promise 对象
函数内的所有值,将自动包装在 resolved 的 promise 中

async function fn() {return 666
}
let result = fn()
console.log(result)  //Promise { 666 }
result.then(res => console.log(res))   //666

6.2 await命令

正常情况下await命令后面是一个 Promise 对象,返回该对象的结果。如果不是 Promise 对象,就直接返回对应的值。
await只能出现在异步函数中!
await能停止代码执行,让后面的同步代码,先执行
await后面跟随的是一个promise对象
await返回的是: Promise对象中的then()中的回调函数中的参数res

async function fn() {return 666
}
console.log('嘻嘻')  //第一个同步先执行async function fn2() {console.log('哈哈')    //第二个同步  let str = await fn()   // await会 暂停函数的执行  但不会影响同步console.log(str)console.log(888);
}
fn2()
console.log(333)           //第三个同步
let result = fn()

6.3加入async和await

//先导入then-fs模块
import thenFs from "then-fs";
async function getpromise() {const a = await thenFs.readFile('./poetry/a.txt', 'utf8')const b = await thenFs.readFile('./poetry/b.txt', 'utf8')const c = await thenFs.readFile('./poetry/c.txt', 'utf8')const d = await thenFs.readFile('./poetry/d.txt', 'utf8')console.log(a)console.log(b)console.log(c)console.log(d)
}
getpromise()

7.promise解决回调地狱(王者)
await需要等待promise执行完毕,所以 await会 暂停函数的执行,但不会影响其他同步任务。
await命令后面的Promise对象,运行结果可能是rejected,所以最好把await命令放在try…catch代码块中
7.1promise三种状态
Promise对象代表一个异步操作,
有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)
一旦状态改变,就不会再变
状态的改变只有两种可能:
从pending(进行中)变为fulfilled(已成功)
从pending(进行中)变为rejected(已失败)
当达到最终的 fulfilled 或 rejected 时,promise的状态就不会再改变了。

7.2Promise.prototype.finally()
finally()方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。该方法是 ES2018 引入标准的。
下面代码中,不管promise最后的状态,在执行完then或catch指定的回调函数以后,都会执行

// 先导入then-fs
import thenFs from 'then-fs';
async function fn() {try {const str1 = await thenFs.readFile('./poetry/a.txt', 'utf8');console.log(str1);const str2 = await thenFs.readFile('./poetry/b.txt', 'utf8');console.log(str2);const str3 = await thenFs.readFile('./poetry/c.txt', 'utf8');console.log(str3);const str4 = await thenFs.readFile('./poetry/d.txt', 'utf8');console.log(str4);} catch (e) {console.log("文件读取错误: " + e.message);} finally {console.log('无论有没有错误都要执行的代码...');}
}
fn();

未完待续…

详解回调地狱以及promise相关推荐

  1. 【JavaScript】回调地狱、Promise

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

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

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

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

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

  4. 回调地狱和Promise

    目录 1.回调地狱callback-hell 由于fs.readFile是异步操作,所以你不能判断下面三个文件的执行顺序 var fs = require('fs')fs.readFile('./da ...

  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. python回调函数实例详解_python 简单的例子下详解回调函数

    回调的英文定义: A callback is a function that is passed as an argument to another function and is executed ...

  8. Promise入门详解和基本用法 我来教你

    JavaScript的执行环境是单线程. 所谓单线程,是指JS引擎中负责解释和执行JavaScript代码的线程只有一个,也就是一次只能完成一项任务,这个任务执行完后才能执行下一个,它会「阻塞」其他任 ...

  9. [绍棠] Promise入门详解和基本用法

    异步调用 异步 JavaScript的执行环境是单线程. 所谓单线程,是指JS引擎中负责解释和执行JavaScript代码的线程只有一个,也就是一次只能完成一项任务,这个任务执行完后才能执行下一个,它 ...

最新文章

  1. php学习,一个简单的Calendar(2) 一个简单的活动页面
  2. Galaxy v-21.01 发布,新的流程和历史栏体验
  3. 原来益生菌是这么搞定致病菌的
  4. 重磅来袭!谷歌八年高级工程师亲授面试经验!!!
  5. 重大合同实为旧事 数据港信披被上交所问询
  6. mysql 线程内存 回收_MySQL内存使用-线程独享
  7. c++面试题【转】 面经
  8. CSS DIV 居中
  9. VS2013出现“无法找到“xxx.exe”的调试信息,或者调试信息不匹配”错误解决方案
  10. Google Guava BloomFilter
  11. REVERSE-PRACTICE-BUUCTF-5
  12. 文件服务器ping延时大,windowns 2008 ping 127.0.0.1延迟大的解决方法。
  13. spring helloworld
  14. 微信公众号开发C#系列-5、用户和用户组管理-支持同步
  15. Pytorch 基本概念
  16. 拓端tecdat|R语言使用二元回归将序数数据建模为多元GLM
  17. iOS 进阶 第二十二天(0603)
  18. 彼之蜜糖,我之砒霜;彼之敝履,吾之瑰宝
  19. js混淆还原工具_技术分享:几种常见的JavaScript混淆和反混淆工具分析实战【转】...
  20. Kali Linux全网最细安装教程

热门文章

  1. 踩坑:EasyExcel导出excel导出数据为空
  2. Principles for Microservice Design: Think IDEALS SOLID
  3. Lecture 1: Probability Models and Axioms
  4. 个人博客项目开发总结(一) 项目架构及后端开发
  5. 电动车行业上演“三国杀”,碳达峰压力下到底谁是老大?
  6. 鼠标经过箭头时,图片会向左或向右…
  7. 民工哥的十年故事:杭漂十年,今撤霸都!
  8. 网络规划中的IP地址分配
  9. Mockito教程一
  10. craco中使用px2rem,进行px转rem,解决分辨率适配问题