前言:

在 Promise 中,异步操作的结果有三种状态:等待(pending)、已完成(fulfilled)和已拒绝(rejected)。当异步操作完成后,Promise 对象会从等待状态转变为已完成或已拒绝状态。如果异步操作成功完成,则 Promise 对象处于已完成状态,并携带着异步操作的返回值;如果异步操作发生错误,则 Promise 对象处于已拒绝状态,并携带着一个错误信息。

Promise 可以通过链式调用来实现多个异步操作依次执行的效果,这种方式比传统的回调函数更加简洁、灵活和易读。

目录

前言:

简介

fs读取文件

Promise封装fs读取文件操作

封装ajax请求

promise的状态改变

Promise工作流程

promise API

关键问题

如何修改对象的状态

promise 如何串连多个操作任务?

promise 异常传透?

中断 promise 链?

自定义(手写)Promise


简介

1.抽象表达:

(1) Promise 是一门新的技术(ES6 规范)

(2) Promise 是JS 中进行异步编程的新解决方案

备注: 旧方案是单纯使用回调函数

2. 具体表达

(1) 从语法上来说: Promise 是一个构造函数

(2) 从功能上来说: promise 对象用来封装一个异步操作并可以获取其成功/失败的结果值

异步编程

  • fs·文件操作 require('fs').readFile('./index.html',(err,data)=>小)
  • 数据库操作
  • AJAX   $.get('/server'(data)=>)
  • 定时器 setTimeout(( )=>{},2000);

3.特点:

①指定回调函数的方式更加灵活

1. 旧的: 必须在启动异步任务前指定

2.promise: 启动异步任务 => 返 promie对象 =>给 promise 对象绑定回调函数(甚至可以在异步任务结束后指定/多个)

②支持链式调用,可以解决回调地狱问题

1. 什么是回调地狱?

回调函数嵌套调用,外部回调函数异步执行的结果是嵌套的回调执行的条件。

2.回调地狱的缺点?

  • 不便于阅读
  • 不便于异常处理

3.解决方案?

promise 链式调用。

案例

Promise 形式实现 都是函数类型的数据

resolve 解决

reject 拒绝

//点击按钮,2 后显示是否中奖(30%概率中奖)
//若中奖弹出恭喜恭喜,奖品为 19万 RMB 劳斯莱斯优惠券。若未中奖弹出再接再厉//生成随机数
function rand(m,n){return Math.ceil(Math.random() * (n-m+1)) + m-1;//Math.ceil()方法返回一个大于或等于数字的最小整数,即向上取整}//获取元素对象
const btn = document.querySelector('#btn');btn.addEventListener('click', function(){const p = new Promise((resolve, reject) => [setTimeout(() => [//30% 1-100 1 2 30//获取从1 - 1的一个随机数let n = rand(1, 100);//判断if(n <= 30){resolve(n); // 将 promise 对象的状态设置为 [成功J}elsef}else{reject(n); // 将 promise 对象的状态设置为 [失败]}}, 1000);});//调用 then 方法 value 值 reason 理由p.then((value) => {alert('恭喜恭喜,奖品为 1万 RMB 劳斯莱斯优惠券,中奖号码为'+value);}, (reason) => {alert("再接再厉,号码为'+reason);}),})

fs读取文件

const fs = require( 'fs')
回调函数 形式
fs.readFile('./resource/content.txt', (err, data) => {// 如果出错 则抛出错误if(err) throw err;//输出文件内容console.log(data.toString());
});

fs是node.js里面的一个模块,叫文件系统模块。

//Promise 形式
let p = new Promise((resolve,reject) => fs .readFile('./resource/content.txt',(err, data) => {//如果出错if(err) reject(err);//如果成功resolve(data);});});//调用 then
p.then(value=>{console.log(value.tostring());},reason =>(console.log(reason);})

Promise封装fs读取文件操作

封装一个函数 mineReadFile 读取文件内容

参数: path 文件路径

返回: promise 对象

function mineReadFile(path){return new Promise((resolve, reject) => {//读取文件require('fs').readFile(path, (err, data) =>{//判断if(err) reject(err);//成功resolve();});});}mineReadFile('./resource/content.txt')
.then(value=>{//输出文件内容console.log(value.tostring());}reason=>[console.log(reason);});

promisify方法进行promise风格转化

传入一个遵循常见的错误优先的回调风格的函数

(即以 (err,value) =>... 回调作为最后一个参数),并返回一个返回 promise 的版本。

//引入 util 模块
const util = require('util');//引入 fs 模块
const fs = require('fs');
//返回一个新的函数
let mineReadFile = util.promisify(fs.readFile);
mineReadFile('./resource/content.txt').then(value=>{console.log(value.tostring());
});

封装ajax请求

封装一个函数 send AJAX 发送 GET AJAX 请求

参数URL

返回结果 Promise 对象

function sendAJAX(url){return new Promise((resolve, reject) => {const xhr = new XMLHttpRequest();xhr.responseType ='json';xhr.open("GET",ur1);xhr.send();//处理结果xhr.onreadystatechange = function(){if(xhr.readyState === 4){//判断成功if(xhr.status >= 20 && xhr.status < 300){//成功的结果resolve(xhr.response);}else{reject(xhr.status);}}}}); sendAJAX('https://api.apiopen.top/getJoke')
.then(value => {console.log(value);}, reason => {console.warn(reason);});

promise的状态改变

pending 变为 resolved

pending 变为 rejected

说明: 只有这 2 种,且一个 promise 对象只能改变一次。

无论变为成功还是失败,都会有一个结果数据

成功的结果数据一般称为 value,失败的结果数据一般称为 reason

Promise 的状态

实例对象中的一个属性

①PromiseState

pending 未决定的

resolved / fullfilled 成功

rejected 失败

②Promise 对象的值

实例对象中的另一个属性 PromiseResult

保存着对象[成功/失败]的结果

resolve

reject


Promise工作流程

promise API

1. Promise 构造函数: Promise (excutor){ }

(1) executor 函数: 执行器(resolve, reject) => { }

(2) resolve 函数: 内部定义成功时我们调用的函数 value =>{ }

(3) reject 函数: 内部定义失败时我们调用的函数 reason =>{ }

说明: executor 会在 Promise 内部立即同步调用,异步操作在执行器中执行

2.Promise.prototype.then 方法: (onResolved, onRejected) => { }

(1) onResolved,函数: 成功的回调函数 (value) =>

(2) onRejected 函数: 失败的回调函数 (reason) =>说明: 指定用于得到成功 value 的成功回调和用于得到失败 reason 的失败回调返回一个新的 promise 对象

3. Promise.prototype.catch 方法:(onRejected) => { }

(1)onRejected 函数: 失败的回调函数 (reason) =>{ }

说明: then( )的语法糖,相当于:then(undefined,onRejected)

4. Promise.resolve 方法: (value) =>{ }

(1) value: 成功的数据 promise 对象

说明: 返回一个成功/失败的 promise 对象

//如果传入的参数为 非Promise类型的对象,则返回的结果为成功promise对象

//如果传入的参数为 Promise 对象,则参数的结果决定了 resolve 的结果

5.Promise.reject 方法:(reason) =>{ }

(1)reason: 失败的原因

说明: 返回一个失败的 promise 对象

6.Promise.all 方法:(promises) => { }

(1) promises: 包含 n 个 promise 的数组

说明: 返回一个新的 promise,只有所有的 promise 都成功才成功,只要有一个失败了就直接失败

7.Promise.race 方法:(promises) =>{ }

(1) promises: 包含 n 个 promise 的数组

说明: 返回一个新的 promise,第一个完成的 promise 的结果状态就是最终的结果状态

(1)Promise 构造函数: Promise(excutor) { }

excutor,函数: 同步执行 (resolve,reject) => { }

resolve 函数: 内部定义成功时我们调用的函数 value => { }

reject 函数:内部定义失败时我们调用的函数 reason => { }

说明: excutor 会在 romise 内部立即同步回调,异步操作在执行器中执行

(2)Promise.prototype.then 方法: (onResolved,onRejected) =>{onResolved 函数:成功的回调函数 (value) => { }

关键问题

如何修改对象的状态

let p = new Promise((resolve, reject) =>{//1.resolve 函数// resolve( 'ok'); // pending=> fulfilled (resolved)//2.reject 函数// reject("error");// pending=> rejected//3。抛出错误throw'出问题了';
});
console.log(p);

一个 promise 指定多个成功/失败回调函数,都会调用吗?

当 promise 改变为对应状态时都会调用。

改变 promise 状态和指定回调函数谁先谁后?

(1)都有可能,正常情况下是先指定回调再改变状态,但也可以先改状态再指定回调。(执行器函数是同步执行的,一般来说会先改变状态。如果resolve写在定时器里,则then先执行)

(2)如何先改状态再指定回调?

  • 在执行器中直接调用 resolve( )/reject( )
  • 延迟更长时间才调用 then( )

(3) 什么时候才能得到数据?

①如果先指定的回调,那当状态发生改变时,回调函数就会调用,得到数据

②如果先改变的状态,那当指定回调时,回调函数就会调用,得到数据

promise.then( )返回的新 promise 的结果状态由什么决定?

(1) 简单表达: 由 then( )指定的回调函数执行的结果决定

(2) 详细表达:

①如果抛出异常,新 promise 变为 reiected,reason 为抛出的异常

②如果返回的是非 promise 的任意值,新 promise变为 resolved, value 为返回的值

③如果返回的是另一个新 promise,此 promise 的结果就会成为新 promise 的结果

即默认result的状态为成功fulfilled的,即使是p.then调用了reject回调函数

如果p.then里面的回调函数有return,并且return了一个Promise对象

那么此时的resut的状态和由returh返的Pomise对象里的状态和值决定。


promise 如何串连多个操作任务?

(1) promise 的 then( )返回一个新的 promise可以开成 then( )的链式调用

(2)通过 then 的链式调用串连多个同步/异步任务

.then的确返回promise对象,但这个对象的值由回调返回的值决定,这里没有声明返回值,所以返回undefined,那么下一个then获取到的值就是undefined,直接打印出来。

promise 异常传透?

(1)当使用 promise 的 then 链式调用时,可以在最后指定失败的回调

(2) 前面任何操作出了异常,都会传到最后失败的回调中处理 catch( )

返回pending的promise,状态没有改变,then方法不可以调用


中断 promise 链?

(1) 当使用 promise 的 then 链式调用时,在中间中断,不再调用后面的回调函数

(2) 办法: 在回调函数中返回一个 pendding,状态的 promise 对象


自定义(手写)Promise

function (window) {//Promise 构造函数//内部同步执行的函数excutor:(resolve,reject) => {function Promise(excutor) {}})
function Promise(executor){//resolve函数function resolve(data){}//reject函数function reject(data){}//同步调用[执行器函数]executor(resolve,reject);
}
Promise.prototype.then = function(onResolved, onRejected){ }

Promise 入门相关推荐

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

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

  2. JS:ES6-8 Promise入门

    概述: Promise (期约)是 ES6 引入的异步编程的新解决方案. 一.promise对象:代表了将来某个将要发生的事件(通常是异步操作),可以将异步操作以同步的流程表达出来,避免了层层嵌套的回 ...

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

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

  4. 在微信小程序的JS脚本中使用Promise来优化函数处理

    在我们传统的Javascript开发函数编写中,我们习惯了回调函数的处理,不过随着回调函数的增多,以及异步处理的复杂性等原因,代码越来越难读,因此诞生了使用Promise来优化JS函数处理的需求,引入 ...

  5. Promise方法汇总

    关于Promise入门介绍请看之前文章--Promise入门         Promise 是异步编程的一种解决方案: 从语法上讲,promise是一个对象,从它可以获取异步操作的消息:从本意上讲, ...

  6. promise常见错误

    导读 上周讲了promise用法,这周我们讲一下promise实战中可能出现得一些易错点,如果对promise基础不是很了解可以去看我的上一篇文章 promise入门 常见问题一 :回调地狱式用法 r ...

  7. 【JavaScript】过了一年,懒癌患者终于整理了一下『手写Promise A+』

    手写前的准备工作: 如果感觉对 Promise 还不太熟悉的就先移步 Promise 入门,及 JS执行机制及Event Loop. Promise A+规范:目前我们使用的 Promise 是基于 ...

  8. 一道让人失眠的 Promise 试题深入分析

    ▲ 点击下方"前端开发博客"关注公众号 回复"答案"查阅 JS最新一题 先把罪魁祸首挂在这里给大家群殴 ???? Promise.resolve().then( ...

  9. 每个 JavaScript 工程师都应懂的33个概念

    简介 这个项目是为了帮助开发者掌握 JavaScript 概念而创立的.它不是必备,但在未来学习(JavaScript)中,可以作为一篇指南. 本篇文章是参照 @leonardomso 创立,英文版项 ...

最新文章

  1. javascript的常见对象总结
  2. Android之自定义view引用xml,Android自定义View在XML中映射错误
  3. 2019腾讯科学WE大会:在小宇宙里看见大宇宙的轮廓
  4. Java核心类库篇3——util
  5. Requests API
  6. 使用BIND安装智能DNS服务器(三)---添加view和acl配置
  7. Codeforces 463D Gargari and Permutations(求k个序列的LCS)
  8. importanturlAndutl
  9. 关于坑爹的编解码问题
  10. caffe2 mdl文件转init_net.pb, predict_net.pb
  11. OriginLab学生版激活码续期
  12. WIN10桌面图标消失,且右键失效
  13. 手把手带你从0完成医疗行业影像图像检测三大经典模型InceptionV3-RestNet50-VGG16(附python源代码及数据库)——改变世界经典人工智能项目实战(一)手把手教学迁移学习
  14. 【python】调用百度智能云API实现手写文字识别
  15. 目标跟踪 OP,CLE,DP,AUC的概念和计算
  16. 存储过程,使用游标,详细过程及详解
  17. 小方块上升组成背景特效 html+css+js
  18. 大学我这样过,成了别人眼中的大神
  19. 分享谷歌浏览器历史版本下载地址和谷歌浏览器驱动历史版本下载地址
  20. MySQL 联合索引(复合索引)详解

热门文章

  1. Dota 2 - Character Art Guide
  2. Pandas-数字前面补0
  3. Shodan Hacking
  4. 分形图的递归算法简介
  5. 字母上一横怎么word里打出来
  6. 猫抓m3u8,遇到该媒体已加密,请注意下载key文件
  7. 第十一届蓝桥杯省赛B组(C/C++组)(第一场)
  8. 【JavaScript】 数组 重要方法详解篇(一)
  9. Typescript助力项目开发:JS切换TS、TS类型定制与思考
  10. NAXX Demo3_JSQ_02 BUG