当我还是一个小白的时候,我翻了很多关于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. 【UE4 设计模式】设计模式一些概念

    定义 设计模式是一套被反复使用的.多数人知晓的.经过分类编目的.代码设计经验的总结. 使用设计模式是为了重用代码.让代码更容易被他人理解.保证代码可靠性. 四人帮 GOF ( Gang of Four ...

  2. UltraSoft - Alpha - Scrum Meeting 2

    Date: Apr 09th, 2020. 会议内容为完成初步的任务分工. Scrum 情况汇报 进度情况 组员 负责 昨日进度 后两日任务 CookieLau PM.后端 继续Django tuto ...

  3. Noip模拟37 2021.8.12

    T1 数列 真是考场上不是数学的乱推柿子,想定理,是数学的没想出来.. 比较悲伤... 列柿子不用动脑子,就是没有想出来$EXgcd$解不定方程,淦.. 解处一组解后利用比较显然的性质: $x+\fr ...

  4. Noip模拟18 2021.7.17 (文化课专场)

    T1 导弹袭击(数学) 显然,我们要找到最优的A,B使得一组a,b优于其他组那么可以列出: $\frac{A}{a_i}+\frac{B}{b_i}<\frac{A}{a_j}+\frac{B} ...

  5. 「总结」$dp1$

    大概就是做点题. 先列一下要做的题目列表,从\(UOJ\)上找的. 129寿司晚宴 348州区划分 370滑稽树上滑稽果 457数树 22外星人 37主旋律 300吉夫特 196线段树 311积劳成疾 ...

  6. iptables 原理及应用

    转自:iptables 原理及应用 iptables是一个Linux下优秀的nat+防火墙工具,我使用该工具以较低配置的传统pc配置了一个灵活强劲的防火墙+nat系统,小有心得,看了网上也有很多这方面 ...

  7. hdu 2189 来生一起走(DP)

    题意: 有N个志愿者.指挥部需要将他们分成若干组,但要求每个组的人数必须为素数.问不同的方案总共有多少.(N个志愿者无差别,即每个组的惟一标识是:人数) 思路: 假设N个人可分为K组,将这K组的人数从 ...

  8. 在Delphi中高效执行JS代码

    因为一些原因,需要进行encodeURIComponent和decodeURIComponent编码,在Delphi中找了一个,首先是发现不能正确编码+号,后面强制处理替换了,勉强可用. 后面发现多次 ...

  9. ansible安装和批量执行命令

    yum install -y ansible 编辑 /etc/ansible/hosts 文件 # This is the default ansible 'hosts' file.## It sho ...

  10. Matlab 中 arburg 函数的理解与实际使用方法

    1. 理解 1.1 Matlab 帮助: a = arburg(x,p)返回与输入数组x的p阶模型相对应的归一化自回归(AR)参数. 如果x是一个向量,则输出数组a是一个行向量. 如果x是矩阵,则参数 ...