企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
## Promise 对象 > 1.Promise 的含义 2.基本用法 3.Promise.prototype.then() 4.Promise.prototype.catch() 5.Promise.prototype.finally() 6.Promise.all() 7.Promise.race() ### Promise的含义 同步和异步 在JavaScript的世界中,所有js代码都是单线程执行的,但是浏览器内部还有其他线程,比如浏览器事件,网络请求等都是其他线程在管理。而且这些操作都是相当耗时的。 如果这些也都是单线程的,那js在执行的时候,就不得不停下来等这些耗时的任务完成了才能继续向下执行。这会导致交互的延迟,体验极差。 为了解决这个问题了,我们将这些耗时的操作呢,处理成异步。就是如果触发请求,请求比较耗时,就先将耗时请求交给其他线程处理,js的主线程继续向下执行。等耗时的操作处理完毕后,通知js主线程执行回调。 ![](https://box.kancloud.cn/bd5c223091a141728baf516d0dd53236_649x361.png) ~~~ $.ajax({ success:function(res){ var res = res // 此处省略一万行代码 }, fail:function () { } }) ~~~ ~~~ asyncFunc1(opt, (...args1) => { asyncFunc2(opt, (...args2) => { asyncFunc3(opt, (...args3) => { asyncFunc4(opt, (...args4) => { // some operation }); }); }); }); ~~~ 这就是所谓的回调地狱。回调嵌套导致了代码阅读性差,可复用性差。 我们希望这样的异步可以: 1.请求数据和处理数据能够分离开 2.代码可阅读性高 3.代码可复用性高 一般我们是采用如下的代码来处理 ~~~ function cb(data) { //处理data的n行代码 } function errorcb(){ //处理请求失败的情况 } function ajax(cb,errorcb) { $.ajax({ success:function(data){ cb&&cb(data) }, fail:function(){ errorcb&&errorcb() } }) } ajax(cb,errorcb); ~~~ Promise写法,Promise集中管理异步请求的运行状态。回调函数处理正常或者异常操作。将ajax的请求状态逻辑和回调逻辑彻底分离开。 ~~~ promise.then(function(value){ //成功的处理函数 },function(error){ //失败的处理函数 }); ~~~ Promise 是异步编程的一种解决方案。除此之外还有Generator函数 ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。 Promise对象有以下两个特点 (1)对象的状态不受外界影响 (2)一旦状态改变,就不会再变,任何时候都可以得到这个结果 三种状态: pending:进行中 fulfilled :已经成功 rejected 已经失败 状态改变: Promise对象的状态改变,只有两种可能: 从pending变为fulfilled 从pending变为rejected。 这两种情况只要发生,状态就凝固了,不会再变了 ### 基本用法 ~~~ const promise = new Promise(function(resolve, reject) { // ... some code if (/* 异步操作成功 */){ resolve(value); } else { reject(error); } }); ~~~ ~~~ function timeout(ms) { return new Promise((resolve, reject) => { setTimeout(resolve, ms, 'done'); }); } timeout(100).then((value) => { console.log(value); }); ~~~ ### Promise.prototype.then() ~~~ getJSON("/posts.json").then(function(json) { return json.post; }).then(function(post) { // ... }); ~~~ 可以连续调用then方法 ~~~ getJSON("/post/1.json").then(function(post) { return getJSON(post.commentURL); }).then(function funcA(comments) { console.log("resolved: ", comments); }, function funcB(err){ console.log("rejected: ", err); }); ~~~ ### Promise.prototype.catch() ~~~ getJSON('/posts.json').then(function(posts) { // ... }).catch(function(error) { // 处理 getJSON 和 前一个回调函数运行时发生的错误 console.log('发生错误!', error); }); ~~~ ### Promise.prototype.finally() ~~~ promise .then(result => {···}) .catch(error => {···}) .finally(() => {···}); ~~~ ~~~ server.listen(port) .then(function () { // ... }) .finally(server.stop); ~~~ ### Promise.all() ~~~ const p = Promise.all([p1, p2, p3]); ~~~ ~~~ // 生成一个Promise对象的数组 const promises = [2, 3, 5, 7, 11, 13].map(function (id) { return getJSON('/post/' + id + ".json"); }); Promise.all(promises).then(function (posts) { // ... }).catch(function(reason){ // ... }); ~~~ ### Promise.race() ~~~ const p = Promise.race([p1, p2, p3]); const p = Promise.race([ fetch('/resource'), new Promise(function (resolve, reject) { setTimeout(() => reject(new Error('request timeout')), 5000) }) ]); p .then(console.log) .catch(console.error); ~~~ 上面代码中,只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。 ### 课后习题 1.用promise实现一个函数,按顺序每隔一秒打印一个数字,范围是1-10。