promise 出来已久,以前一直使用,没有仔细剖析原理,最近在复习es6的知识,写一下自己对于promise的理解。

  promise是es6的一种异步编程解决方案,避免频繁的回调函数,增强代码的可阅读性。

  写法很简单:   

    let p2 = new Promise((reslove, reject) => {
reslove(1)
}) console.log(p2.then(res => {
alert(res)
}))

  Promise是内置的构造函数,reslove、reject是固定的,只能这么写。reslove()表示成功,reject()表示失败。

  方法:

  1. then()   then是Promise的核心方法,是用来获取异步的返回结果。有两个参数用来获取reslove 或 reject 的值。
  2. catch()  用来捕获异常。
  3. all() 多个promise,所有的参与的promise对象全部执行完才会出结果。参数为类数组对象。
  4. race() 参数为类数组对象,任何一个参与的promise对象执行完,就会出结果。

  以上为常用的四个方法。

  代码:

  

/*
*
* promise
* 异步编程的一种解决方案。
*
* */
const promise = new Promise(function (reslove, reject) {
console.log('开始')
setTimeout(function () {
reslove(2)
}, 3000)
}) promise.then(function (value) {
return 3;
}).then(function (value) { }) //
let p = new Promise((reslove, reject) => {
setTimeout(()=>{
let a = Math.random();
if (a>0.5) {
//reslove(a); // 这里说白了是就是调用下面的then中的函数 a
reslove.call(null, a) // 这样也行
} else { reject(a) // 调用b
}
reject(a) // 调用b
}, 1000)
}) p.then(res => { // 假设这是函数a
return res;
}, rej => { // 函数b
return rej;
}).then(success => { // 链式调用的重点是前边的then必须return 否则 为undefined
return success;
}, fail => {
return fail;
}) // then() then方法是挂在Promise.prototype上的
console.log(Promise.prototype) // Promise {constructor: ƒ, then: ƒ, catch: ƒ, finally: ƒ, Symbol(Symbol.toStringTag): "Promise"} // catch() 相当于 then(null, reject)
p.then(rel => {
console.log(rel)
return rel;
},rej => {
console.log(rej + '小')
return rej;
}).then(rel => { // 前一个then返回成功或失败都在这里 因为执行catch()后返回一个新的实例该实例该实例执行完之后会变为reslove ,因此后边的catch始终执行不到
console.log(rel)
alert(2)
}).catch(rej => { // 这句是走不到的
console.log(rej)
alert(1)
console.log('二小')
}) // finally() 状态成功或失败 都会执行此操作
let p1 = new Promise((reslove, reject) => {
console.log(this) // window 箭头函数本身没有this 因此this指向定义箭头函数时的上下文
reslove(1);
}) p1.then(res => {
console.log('success')
}).finally(res => {
console.log('finally')
}) // all() 所有实例的状态都改变完才改变
let p2 = new Promise((reslove, reject) => {
setTimeout(() => {
alert(1)
reslove(1)
} ,1000)
}) let p3 = new Promise((reslove, reject) => {
setTimeout(() => {
alert(2)
reslove(2)
} ,2000)
}) let p4 = new Promise((reslove, reject) => {
setTimeout(() => {
alert(3)
reject(3)
} ,3000)
})
Promise.all([p2, p3]).then(res => {
console.log(res) // [1, 2]
}) Promise.all([p2, p3, p4]).then(res => {
console.log(res)
}).catch(rej => {
console.log(rej) // 3 只要有一个reject 就走这里 不走上边的then 返回的永远是第一个reject的promise实例
})
// race()
Promise.race([p2, p3]).then(res => {
console.log(res) // 1
})

  下面是手写的实现promise的原理:

  

// 实现 promise
function MyPromise(fn){ // fn 为 new Promise(fn)
let _this = this;
_this.status = 'pending';
_this.resloveValue = null; // 成功时的数据
_this.rejectValue = null; // 失败时的数据
_this.resloveFnCallbacks = [];
_this.rejectFnCallbacks = []; function reslove(value) {
if (_this.status == 'pending') {
_this.status = 'resloved';
_this.resloveValue = value;
_this.resloveFnCallbacks.forEach(fn => fn())
}
}
function reject(value) {
if (_this.status == 'pending') {
_this.status = 'rejected';
_this.rejectValue = value;
_this.rejectFnCallbacks.forEach(fn => fn())
} }
// 捕获异常
try{
fn(reslove, reject)
} catch (e) {
reject(e)
} } // then() 应该接受两个参数 成功 或 失败的 回调
MyPromise.prototype.then = function (resloveFn, rejectFn) {
let _this = this;
let promise2; // then 返回的promise // 参数非函数转为函数
resloveFn = typeof resloveFn === 'function'? resloveFn: (function (value) {
return value;
}) rejectFn = typeof rejectFn === 'function'? rejectFn: function (err) {
throw err;
} if(this.status == 'resloved') { // 成功
alert(3)
promise2 = new MyPromise((reslove, reject) => {
setTimeout(() => {
let x = resloveFn(this.resloveValue);
resolvePromise(promise2, x, reslove, reject);
})
})
} if(this.status == 'rejected') { // 失败
rejectFn(this.rejectValue)
} if (this.status == 'pending') {
this.resloveFnCallbacks.push(function(){
resloveFn(_this.resloveValue)
})
this.rejectFnCallbacks.push(function(){
rejectFn(_this.rejectValue)
})
} return promise2; // resolvePromise
function resolvePromise(promise2, x, reslove, reject) {
let called; // 是否调用过 // 判断上一次then返回的值 实质上下一个then只需要一个值便可以,所以我们就是要将上一个的peomise中的值提取出来
// then 返回promise只是为了链式调用,then本身需要一个实际的值,并不需要promise
if (x != null && (typeof x === 'object' || typeof x === 'function')) {
try {
let then = x.then; // 保存x的then方法 这种是x是对象
if (typeof then === 'function') {
then.call(x, function (y) {
if (called) return;
called = true;
resolvePromise(promise2, y, reslove, reject)
}, function (rej) {
if (called) return;
called = true;
reject(rej) })
} else { // x 是普通对象直接返回就行
reslove(x);
}
} catch (e) {
if (called) return;
called = true;
reject(e)
}
} else { // x 是普通值
reslove(x)
}
} } // 将promise
let p6 = new MyPromise(function(reslove, reject) {
reslove(2)
})
p6.then(function(res){
return res;
}).then(function(res){
alert(res)
})

  参考链接:https://juejin.im/post/5ab20c58f265da23a228fe0f

 

道可道,非常道——详解promise的更多相关文章

  1. “全栈2019”Java第七十三章:外部类里多个静态非静态内部类详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  2. [GO语言的并发之道] Goroutine调度原理&Channel详解

    并发(并行),一直以来都是一个编程语言里的核心主题之一,也是被开发者关注最多的话题:Go语言作为一个出道以来就自带 『高并发』光环的富二代编程语言,它的并发(并行)编程肯定是值得开发者去探究的,而Go ...

  3. 详解promise、async和await的执行顺序

    1.题目和答案 一道题题目:下面这段promise.async和await代码,请问控制台打印的顺序? async function async1(){ console.log('async1 sta ...

  4. PHP中静态(static)调用非静态方法详解

    1.PHP中可以静态调用非静态方法么? 今天我被问到PHP中可不可以使用 className::methodName() 的方法来调用一个没有声明static的方法.在我的印象中,我好像是见过这种用法 ...

  5. static静态和非静态详解

    static 作为Java中的一个关键字,用于修饰方法.成员变量(Field),统称为成员. 有static修饰的成员   属于类 1.方法称为静态方法(类方法),Field称为类的属性. 2.静态成 ...

  6. PHP中静态(static)调用非静态方法详解--调用!!!

    来源:https://www.cnblogs.com/yolo-bean/p/7739265.html 这里分析了php面向对象中static静态属性和静态方法的调用.关于它们的调用(能不能调用,怎么 ...

  7. Promise和async await详解

    本文转载自Promise和async await详解 Promise 状态 pending: 初始状态, 非 fulfilled 或 rejected. fulfilled: 成功的操作. rejec ...

  8. es6的promise用法详解

    es6的promise用法详解 promise 原理 promise是es6的异步编程解决方案, 是es6封装好的对象: 一个promise有三种状态:Pending(进行中).Resolved(已完 ...

  9. 详解收发不畅原因及U-Mail邮件中继解决之道

    邮件在商务往来中扮演着信息交流的重要角色,假如传输受阻,必将造成沟通不畅:可能三五封邮件的投递你意识不到其重要性,但假如长期需和客户保持沟 通,则需要保证其一贯的稳定性,这就很考验相关软件平台的性能是 ...

随机推荐

  1. 【阿里聚安全·安全周刊】500万台Android设备受感染|YouTube封杀枪支组装视频

    本周的七个关键词:  500万Android 设备受感染丨 黑客将矛头指向无线传输协议 丨  YouTube封杀枪支视频 丨 AMD将发布补丁 丨 Gooligan Android 僵尸网络 丨  N ...

  2. linux内核管理

      一  linux组成:kernel.库.rootfs.程序 1.kernel的功能: 1) kernel提供的功能都通过系统调用给用户接口 2) kernel包括:进程管理 .内存管理 .网络管理 ...

  3. Jenkins + Docker 持续集成

    Jenkins介绍 Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能. 安装部署Jenkins ...

  4. MySQL的入门

    SHOW VARIABLES LIKE 'storage_engine%' #查看引擎 ALTER TABLE `studten` RENAME `student1` #修改表名 ALTER TABL ...

  5. openjudge(三)

    已知三角形的三边分别是a.b.c, 先算出周长的一半s=1/2(a+b+c) 则该三角形面积S=根号[s(s-a)(s-b)(s-c)] 这个公式叫海伦--秦九昭公式 证明: 设三角形的三边a.b.c ...

  6. linux小白成长之路7————Docker安装mysql

    [内容指引] 从Docker检索mysql镜像: Mysql Docker镜像下载: 查看本地镜像列表: 设置Mysql的Docker镜像开机自动运行: 常用Docker指令及参数: 1.从Docke ...

  7. 在Python中使用Redis

    在Python中要使用Redis数据库,首先要安装redis 之前的博客中有写到在命令行模式下操作Redis数据库. 要在项目中使用的话可以这么做: 通过初始化 redis.Redis,得到返回的对象 ...

  8. Git详细教程(2)---多人协作开发

    Git可以完成两件事情: 1. 版本控制 2.多人协作开发 如今的项目,规模越来越大,功能越来越多,需要有一个团队进行开发. 如果有多个开发人员共同开发一个项目,如何进行协作的呢. Git提供了一个非 ...

  9. Linux x86_64内核中断初始化

    Linux x86_64内核中断初始化 [TOC] 中断分类 Linux系统中,中断分为: 硬中断:由外部设备或者执行异常产生的需要快速处理的中断.如缺页中断.定时器硬件中断. 根据内部产生还是外部产 ...

  10. 系统右键添加cmd命令

    我们运行cmd.exe时,会发现刚刚打开时,一般提示在默认路径下: 有时候我们希望直接能够切换到某个路径下运行程序或者做某些工作,那么切换路径可能就会比较麻烦.下面我们介绍一种比较实用的方法,用鼠标右 ...