当我还是一个小白的时候,我翻了很多关于Promise介绍的文档,我一直没能理解所谓解决异步操作的痛点是什么意思

直到我翻了谷歌第一页的所有中文文档我才有所顿悟,其实从他的英文字面意思理解最为简单粗暴

这就是一个承诺,相当于在代码中提供一个在任何时候承诺之后要做什么事的方式,这个承诺可能会兑现也可能无法兑现,当然也可能在兑现的过程中

用这个来替代我们曾经需要写的回调函数,可以避免JavaScript程序中的回调地狱

所以先不去学习的语法,从另一个方式先理解,希望可以帮助你更好的学习或上手Promise

什么是Promise?

Promise是异步编程的一种解决方案,可以替代传统的解决方案,比如回调函数和事件

其在ES6中统一了用法,并提供了原生的Promise对象Promise对象表示异步操作的最终完成(或失败)及其结果值

作为对象,Promise有以下两个特点:

  1. 对象的状态不受外界影响

    • 只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态,

      这也是Promise这个名字的由来,它的英语意思就是承诺,表示其他手段无法改变
  2. 一旦状态改变了就不会在变,也就是说任何时候Promise都只有一种状态
    • pending:初始状态,不是成功或失败状态;

      fulfilled(resolved):操作成功完成状态;

      rejected:操作失败状态
    • Promise对象的状态改变,只有两种可能:从Pending变为Resolved和从Pending变为Rejected

      只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,

      就算改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果,

      这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的

Promise的创建和用途

  1. 构造函数接受一个名为executor的函数,此执行函数接受两个f函数参数,resolvereject
        new Promise( /* executor */ function(resolve, reject { ... }) );
  1. Promise通常用于阻塞代码和异步操作,其中包括文件调用,API调用,DB调用,IO调用等等
  2. 这些异步操作的启动发生在执行函数中,如果异步操作成功,则通过promise的创建者调用resolve()函数返回预期结果,

    同样,如果出现意外错误,则通过调用reject()函数传递错误具体信息
  3. 由于promise会立即执行,我们无法检查promise的初始状态,所以创建一个需要时间执行的promise最简单的方式就是

    使用setTimeOut()函数,通过浏览器控制台的输出可以直观看到之前所说的状态,以及他的变化过程
	var promiseFir = new Promise(function(resolve, reject) {
setTimeout(function() {
resolve({
message: '与大家分享知识很开心!',
code: 200
});
}, 2000)
})
console.log(promiseFir);
setTimeout(function() {
console.log(promiseFir);
}, 2000)

Promise的方法

  1. 3种原型方法

	// 用一个小故事举例,你是一个上学的孩子,你问你的妈妈要一个电话。她说: 这个月底我要买一部手机
var momsPromise = new Promise(function(resolve, reject) {
momsSavings = 20000; // 因为妈妈没有足够储蓄所以无法买到礼物
// momsSavings = 200000; // 如果妈妈有足够的储蓄就可以买到礼物
priceOfPhone = 60000;
if (momsSavings > priceOfPhone) {
resolve({
brand: "iphone",
model: "6s"
});
} else {
reject("我们没有足够的储蓄,让我们多存点钱吧。");
}
});
momsPromise.then(function(value) {
console.log("哇,我得到这个电话作为礼物 ", JSON.stringify(value));
});
momsPromise.catch(function(reason) {
console.log("妈妈不能给我买电话,因为 ", reason);
});
momsPromise.finally(function() {
console.log(
"不管妈妈能不能给我买个电话,我仍然爱她"
);
});
  1. 4种静态方法

Promise.prototype.then(onFulfilled, onRejected) 链式操作

  1. Promise.prototype.then()方法返回的是一个新的Promise对象,因此可以采用链式写法
  2. Promise.prototype.then()方法带有以下三个参数:成功回调,失败回调,前进回调,一般情况下只需要实现第一个,后面是可选的
	function ptFir() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
console.log('方法1执行');
resolve('方法1执行完毕');
}, 2000)
})
}
function ptSec() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
console.log('方法2执行');
resolve('方法2执行完毕');
}, 1000)
})
}
function ptThi() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
console.log('方法3执行');
resolve('方法3执行完毕');
}, 3000)
})
}
ptFir().then(function(data) {
console.log('第一个回调:' + data);
return ptSec();
}).then(function(data) {
console.log('第二个回调:' + data);
return ptThi();
}).then(function(data) {
console.log('第三个回调:' + data);
return '还没完?该结束了吧!';
}).then(function(data) {
console.log(data);
})

Promise.prototype.catch(onRejected) 捕捉错误

  1. Promise.prototype.catch()方法是Promise.prototype.then(null, rejection)的别名,用于指定发生错误时的回调函数
  2. Promise对象的错误具有"冒泡"性质,会一直向后传递,直到被捕获为止,也就是说,错误总是会被下一个catch语句捕获
	promise().then(function(data) {
// todo something
}).catch(function(err) {
// 处理上个回调函数的错误
})

Promise.prototype.finally(onFinally) 最终操作

不管promise对象最后的状态,在执行完.thencatch指定的回调函数以后,都会执行finally方法指定的回调函数

	promise().then(function(data) {
// todo something
}).catch(function(err) {
// 处理上个回调函数的错误
}).finally(function(result) {
// 处理then/catch之后必须执行的操作
})

Promise.resolve() / Promise.reject()

  1. 这两个是帮助方法或快捷方式,它们可以帮助您轻松创建resolvereject方法
  2. 需要注意的是:如果Promise.resolve()方法的参数,

    不是具有.then()方法的对象(又称thenable对象),则返回一个新的Promise对象,且它的状态为fulfilled

    如果Promise.resolve方法的参数是一个Promise对象的实例,则会被原封不动地返回
  3. Promise.reject()方法同上
	var promise = Promise.resolve('Hello,这里是执行成功的内容!');
// var promise = Promise.reject('出错了,这里是被发现的错误!'); // 成功和失败只会有一种状态哦
promise.then(function(data) {
console.log(data)
});
promise.catch(function(err) {
console.log(err)
});

Promise.all()

  1. 当你处理多个promise时,最好先创建一个promise数组,然后对这些promise集执行必要的操作
  2. Promise.all(iterable) 方法返回一个Promise实例,此实例在iterable参数内所有的promise
  3. 都完成(resolved)或参数中不包含promise时回调完成(resolve)
  4. 如果参数中promise有一个失败(rejected),此实例回调失败(reject),失败原因的是第一个失败promise的结果
  5. 注意!!!这里的异步操作是并行执行的,等到它们都执行完后才会进到then()里面,

    并且all()方法会把所有异步操作的结果放进一个数组中传给then()
  6. 下面的示例需要说明的内容
    • 只有3个方法的状态都变成fulfilled,p的状态才会变成fulfilled,此时3个方法的返回值组成一个数组,传递给p的回调函数
    • 只要3个方法之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数
	function ptFir() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
console.log('方法1执行');
resolve('方法1执行完毕');
}, 2000)
})
}
function ptSec() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
console.log('方法2执行');
resolve('方法2执行完毕');
}, 1000)
})
}
function ptThi() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
console.log('方法3执行');
resolve('方法3执行完毕');
}, 3000)
})
}
Promise.all([ptFir(), ptSec(), ptThi()]).then(function(data) {
console.log(data);
console.log({}.toString.call(data));
})

Promise.race()

  1. Promise.race(iterable)方法返回一个promise,一旦迭代器中的某个promise解决或拒绝,返回的promise就会解决或拒绝
  2. all()方法的效果实际上是「谁跑的慢,以谁为准执行回调」

    那么相对的就有另一个方法「谁跑的快,以谁为准执行回调」,这就是race()方法,这个词本来就是赛跑的意思
  3. 这个race()方法有什么用呢?使用场景还是很多的,比如我们可以用race()给某个异步请求设置超时时间,

    并且在超时后执行相应的操作
	// ptFir(), ptSec(), ptThi() 同上
Promise.all([ptFir(), ptSec(), ptThi()]).then(function(data) {
console.log(data);
console.log({}.toString.call(data));
})

使用Promise的一些经验法则

  1. 进行异步操作或使用阻塞代码时,请使用Promise
  2. 为了代码的可读性,resolve()方法对待.then(), reject()方法对应.catch()
  3. 确保同时写入.catch().then()方法来实现所有的promise
  4. 如果在这两种情况下都需要做一些事情,请使用.finally()
  5. 我们只有一次改变每个promise (单一原则)
  6. 我们可以在一个promise中添加多个处理程序
  7. Promise对象中所有方法的返回类型,无论是静态方法还是原型方法,都是Promise
  8. all()方法中,无论哪个promise首先未完成,promise的顺序都保持在值变量中

参考文档一 ———— 彻底理解Javascript 中的 Promise

参考文档二 ———— 通俗浅显的理解Promise中的then

参考文档三 ———— 理解 Javascript 中的 Promise

参考文档四 ———— JavaScript Promise 对象

我是 fx67ll.com,如果您发现本文有什么错误,欢迎在评论区讨论指正,感谢您的阅读!

如果您喜欢这篇文章,欢迎访问我的 本文github仓库地址,为我点一颗Star,Thanks~

转发请注明参考文章地址,非常感谢!!!

快速入门上手JavaScript中的Promise的更多相关文章

  1. webpack快速入门——处理HTML中的图片

    在webpack中是不喜欢你使用标签<img>来引入图片的,但是我们作前端的人特别热衷于这种写法, 国人也为此开发了一个:html-withimg-loader.他可以很好的处理我们在ht ...

  2. javascript中的promise和deferred:实践(二)

    javascript中的promise和deferred:实践(二) 介绍: 在第一节呢,我花了大量的时间来介绍promises和deferreds的理论.现在呢,我们来看看jquery中的promi ...

  3. JavaScript中的Promise【期约】[未完成]

    JavaScript中的Promise[期约] 期约主要有两大用途 首先是抽象地表示一个异步操作.期约的状态代表期约是否完成. 比如,假设期约要向服务器发送一个 HTTP 请求.请求返回 200~29 ...

  4. Vue.js——60分钟快速入门 开发· webpack 中文文档

    转载于:http://www.cnblogs.com/keepfool/p/5619070.html http://www.css88.com/doc/webpack2/guides/get-star ...

  5. 通过一道笔试题浅谈javascript中的promise对象

    因为前几天做了一个promise对象捕获错误的面试题目,所以这几天又重温了一下promise对象.现在借这道题来分享下一些很基础的知识点. 下面是一个面试题目,三个promise对象捕获错误的例子,返 ...

  6. Javascript中的Promise

    Promise定义 Promise是CommonJs的规范之一,包含resolve,reject,done,fail,then等方法,能够帮助我们控制代码的流程,避免函数的多层嵌套.异步在web开发中 ...

  7. R语言快速入门上手

    导言:     较早之前就听说R是一门便捷的数据分析工具,但由于课程设计的原因,一直没有空出足够时间来进行学习.最近自从决定本科毕业出来找工作之后,渐渐开始接触大数据行业的技术,现在觉得是时候把R拿下 ...

  8. 掌握JavaScript中的Promise,实现异步编程

    事件循环 基本介绍 JavaScript是一门单线程的编程语言,所以没有真正意义上的并行特性. 为了协调事件处理.页面交互.脚本调用.UI渲染.网络请求等行为对主线程造成的影响,事件循环(event ...

  9. 彻底理解Javascript 中的 Promise(-------------------------------***---------------------------------)

    ES6原生提供了 Promise 对象. 到底是何方妖怪呢?打出来看看: 所谓 Promise,就是一个对象,用来传递异步操作的消息.它代表了某个未来才会知道结果的事件(通常是一个异步操作),并且这个 ...

随机推荐

  1. Kubernetes-Service介绍(三)-Ingress(含最新版安装踩坑实践)

    前言 本篇是Kubernetes第十篇,大家一定要把环境搭建起来,看是解决不了问题的,必须实战. Kubernetes系列文章: Kubernetes介绍 Kubernetes环境搭建 Kuberne ...

  2. __str__ __repr__区别

    当print 实例化对象的时候,可以直接输出__str__ 中的 return结果 在console中 直接输实例对象c 只能输出<__main__.Cycle object at 0x0000 ...

  3. 天脉2(ACoreOS653)操作系统学习02

    天脉2(ACoreOS653)操作系统学习02 一.分区内通信方法 分区内通信指同一分区内进程之间的通信.ARINC 653定义的分区内进程通信机制,包括:缓存队列(Buffers-Queue).黑板 ...

  4. 【UE4 C++ 基础知识】<1> UPROPERTY宏、属性说明符、元数据说明符

    属性声明 属性使用标准的C++变量语法声明,前面用UPROPERTY宏来定义属性元数据和变量说明符. UPROPERTY([specifier, specifier, ...], [meta(key= ...

  5. Windows平台编译器相关的几个预定义宏

    WIN32 是在windows.h 中定义的宏,包含winodws.h则定义该宏 _WIN32/_WIN64跟windows平台有关的宏,_WIN32在windows   32位和64位下都有该宏,_ ...

  6. 字符串与模式匹配算法(一):BF算法

    一.BF算法的基本思想 BF(Brute Force)算法是模式匹配中最简单.最直观的算法.该算法最基本的思想是从主串的第 start 个字符起和模式P(要检索的子串)的第1个字符比较,如果相等,则逐 ...

  7. Luogu P1084 疫情控制 | 二分答案 贪心

    题目链接 观察题目,答案明显具有单调性. 因为如果用$x$小时能够控制疫情,那么用$(x+1)$小时也一定能控制疫情. 由此想到二分答案,将问题转换为判断用$x$小时是否能控制疫情. 对于那些在$x$ ...

  8. poj 2724 Purifying Machine(二分图最大匹配)

    题意: 有2^N块奶酪,编号为00...0到11..1. 有一台机器,有N个开关.每个开关可以置0或置1,或者置*.但是规定N个开关中最多只能有一个开关置*. 一旦打开机器的开关,机器将根据N个开关的 ...

  9. v-html | 数据内容包含元素标签或者样式

    问题 如果我们展示的数据包含元素标签或者样式,我们想展示标签或样式所定义的属性作用,该怎么进行渲染 插值表达式{{}}和v-text指令被直接解析为了字符串元素. <body> <d ...

  10. 微信小程序小窗无效

    这里算是踩过一个坑吧 1.自己的调试版本库是否在这个版本或者以上 2.编辑器是不能看到小窗效果的,只能在真机运行 3.播放的内容是否有效,是否能播放 4.跳转页面时内容是否处于播放状态 5.当前页面是 ...