什么是Promise

Promise是异步编程的一种解决方案,说白了就是一个构造函数,带有all,reject,resolve这几个方法,圆形上有then,catch等方法

Promise的特点

  • 对象的状态不受外界影响,他的对象代表的是一个异步操作,只有三种状态,pending(进行中)fulfilled(已成功)rejected(已失败)只有异步操作可以决定当前是哪一种状态,其他任何操作都无法改变这个状态,这也是Promise这个名字的由来,翻译成中文就是承诺的意思,表示一旦对象生成,其他手段都无法改变。
  • 一旦状态发生改变,就不会再便,任何时候都可以得到这个结果。Promise对象的状态改变只有两种可能,从pending变为fullfilled以及从pending变为rejected 只要这两种情况发生,状态就定死了,不会在改变了,就会一直保持这个结果,这事就成为resolve(定形完成),如果状态已经发生了,在对Promise对象添加回调函数,也会立即得到这个结果。这个与event完全不一样,event的特点是如果错过了事见再去监听这个event事见,是得不到这个结果的

Promise的用法

我们先创建一个Promise

let e = new Promise (function (resolve,reject){
settimeout (function(){
console.log('执行完成Promise')
resolve('此处执行当请求完成后 Promise返回的结果')
},2000)
})

其执行过程是:执行了一个异步操作,也就是setTimeout,2秒后,输出“执行完成”,并且调用resolve方法。

注意!我只是new了一个对象,并没有调用它,我们传进去的函数就已经执行了,这是需要注意的一个细节。所以我们用Promise的时候一般是包在一个函数中,在需要的时候去运行这个函数,如:

<div onClick={promiseClick}>开始异步请求</div>

const promiseClick =()=>{
console.log('点击方法被调用')
let p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
console.log('执行完成Promise');
resolve('要返回的数据可以任何数据例如接口返回数据');
}, 2000);
});
return p
}

放在函数里面的时候只有调用的时候才会被执行

那么,接下里解决两个问题:

1、为什么要放在函数里面

2、resolve是个什么鬼

我们包装好的函数最后,会return出Promise对象,也就是说,执行这个函数我们得到了一个Promise对象。接下来就可以用Promise对象上有then、catch方法了,这就是Promise的强大之处了,看下面的代码:


promiseClick().then(function(data){
console.log(data);
//后面可以用传过来的数据做些其他操作
//......
});

先是方法被调用起床执行了promise,最后执行了promise的then方法,then方法是一个函数接受一个参数是接受resolve返回的数据这事就输出了‘要返回的数据可以任何数据例如接口返回数据’

这时候你应该有所领悟了,原来then里面的函数就跟我们平时的回调函数一个意思,能够在promiseClick这个异步任务执行完成之后被执行。这就是Promise的作用了,简单来讲,就是能把原来的回调写法分离出来,在异步操作执行完后,用链式调用的方式执行回调函数。

你可能会觉得在这个和写一个回调函数没有什么区别;那么,如果有多层回调该怎么办?如果callback也是一个异步操作,而且执行完后也需要有相应的回调函数,该怎么办呢?总不能再定义一个callback2,然后给callback传进去吧。而Promise的优势在于,可以在then方法中继续写Promise对象并返回,然后继续调用then来进行回调操作。

所以:精髓在于:Promise只是能够简化层层回调的写法,而实质上,Promise的精髓是“状态”,用维护状态、传递状态的方式来使得回调函数能够及时调用,它比传递callback函数要简单、灵活的多。所以使用Promise的正确场景是这样的:


promiseClick()
.then(function(data){
console.log(data);
return runAsync2();
})
.then(function(data){
console.log(data);
return runAsync3();
})
.then(function(data){
console.log(data);
});

reject的用法

`以上是对resolve状态是的用法,resolve相当于是对promise成功时候窒息感的回掉函数,状态值修改为fullfiled,,那么,reject就是失败的时候的回调,他把promise的状态修改为rejected,这样我们在then中就能捕捉到,然后执行“失败”情况的回调。

function promiseClick(){
let p = new Promise(function(resolve, reject){
setTimeout(function(){
var num = Math.ceil(Math.random()*20); //生成1-10的随机数
console.log('随机数生成的值:',num)
if(num<=10){
resolve(num);
}
else{
reject('数字太于10了即将执行失败回调');
}
}, 2000);
})
return p
} promiseClick().then(
function(data){
console.log('resolved成功回调');
console.log('成功回调接受的值:',data);
},
function(reason, data){
console.log('rejected失败回调');
console.log('失败执行回调抛出失败原因:',reason);
}
);

以上代码:调用promiseClick方法执行,2秒后获取到一个随机数,如果小于10,我们算成功,调用resolve修改Promise的状态为fullfiled。否则我们认为是“失败”了,调用reject并传递一个参数,作为失败的原因。并将状态改成rejected

运行promiseClick并且在then中传了两个参数,这两个参数分别是两个函数,then方法可以接受两个参数,第一个对应resolve的回调,第二个对应reject的回调。(也就是说then方法中接受两个回调,一个成功的回调函数,一个失败的回调函数,并且能在回调函数中拿到成功的数据和失败的原因),所以我们能够分别拿到成功和失败传过来的数据就有以上的运行结果

catch用法

catch的用法和结果有点类似于reject,即失败的时候执行的回调函数,主要是用来捕捉异常.


function promiseClick(){
let p = new Promise(function(resolve, reject){
setTimeout(function(){
var num = Math.ceil(Math.random()*20); //生成1-10的随机数
console.log('随机数生成的值:',num)
if(num<=10){
resolve(num);
}
else{
reject('数字太于10了即将执行失败回调');
}
}, 2000);
})
return p
} promiseClick().then(
function(data){
console.log('resolved成功回调');
console.log('成功回调接受的值:',data);
}
)
.catch(function(reason, data){
console.log('catch到rejected失败回调');
console.log('catch失败执行回调抛出失败原因:',reason);
});

效果和写在then的第二个参数里面一样。它将大于10的情况下的失败回调的原因输出,但是,它还有另外一个作用:在执行resolve的回调(也就是上面then中的第一个参数)时,如果抛出异常了(代码出错了),那么并不会报错卡死js,而是会进到这个catch方法中。如下:

function promiseClick(){
let p = new Promise(function(resolve, reject){
setTimeout(function(){
var num = Math.ceil(Math.random()*20); //生成1-10的随机数
console.log('随机数生成的值:',num)
if(num<=10){
resolve(num);
}
else{
reject('数字太于10了即将执行失败回调');
}
}, 2000);
})
return p
} promiseClick().then(
function(data){
console.log('resolved成功回调');
console.log('成功回调接受的值:',data);
console.log(noData);
}
)
.catch(function(reason, data){
console.log('catch到rejected失败回调');
console.log('catch失败执行回调抛出失败原因:',reason);

在resolve回调中,我们console.lognodata这个变量 传统的情况下是会报错的,即当代码执行到此处的时候就会抛出错误,浏览器不会继续执行下去。但是以上如果使用了catch,就没有报错并且会得到结果,也就是说进到catch方法里面去了,而且把错误原因传到了reason参数中。即便是有错误的代码也不会报错了

all的用法

与then同级的另一个方法,all方法,该方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后并且执行结果都是成功的时候才执行回调。

将上述方法复制两份并重命名promiseClick3(), promiseClick2(), promiseClick1(),如下


function promiseClick1(){
let p = new Promise(function(resolve, reject){
setTimeout(function(){
var num = Math.ceil(Math.random()*20); //生成1-10的随机数
console.log('随机数生成的值:',num)
if(num<=10){
resolve(num);
}
else{
reject('数字太于10了即将执行失败回调');
}
}, 2000);
})
return p
}
function promiseClick2(){
let p = new Promise(function(resolve, reject){
setTimeout(function(){
var num = Math.ceil(Math.random()*20); //生成1-10的随机数
console.log('随机数生成的值:',num)
if(num<=10){
resolve(num);
}
else{
reject('数字太于10了即将执行失败回调');
}
}, 2000);
})
return p
}
function promiseClick3(){
let p = new Promise(function(resolve, reject){
setTimeout(function(){
var num = Math.ceil(Math.random()*20); //生成1-10的随机数
console.log('随机数生成的值:',num)
if(num<=10){
resolve(num);
}
else{
reject('数字太于10了即将执行失败回调');
}
}, 2000);
})
return p
} Promise
.all([promiseClick3(), promiseClick2(), promiseClick1()])
.then(function(results){
console.log(results);
})

Promise.all来执行,all接收一个数组参数,这组参数为需要执行异步操作的所有方法,里面的值最终都算返回Promise对象。这样,三个异步操作的并行执行的,等到它们都执行完后才会进到then里面。那么,三个异步操作返回的数据哪里去了呢?都在then里面,all会把所有异步操作的结果放进一个数组中传给then,然后再执行then方法的成功回调将结果接收,结果如下:(分别执行得到结果,all统一执行完三个函数并将值存在一个数组里面返回给then进行回调输出)

race的用法

race的用法与all相对立,all是等所有的异步操作都执行完了再执行then方法,那么race方法就是相反的,谁先执行完成就先执行回调


function promiseClick1(){
let p = new Promise(function(resolve, reject){
setTimeout(function(){
var num = Math.ceil(Math.random()*20); //生成1-10的随机数
console.log('2s随机数生成的值:',num)
if(num<=10){
resolve(num);
}
else{
reject('2s数字太于10了即将执行失败回调');
}
}, 2000);
})
return p
}
function promiseClick2(){
let p = new Promise(function(resolve, reject){
setTimeout(function(){
var num = Math.ceil(Math.random()*20); //生成1-10的随机数
console.log('3s随机数生成的值:',num)
if(num<=10){
resolve(num);
}
else{
reject('3s数字太于10了即将执行失败回调');
}
}, 3000);
})
return p
}
function promiseClick3(){
let p = new Promise(function(resolve, reject){
setTimeout(function(){
var num = Math.ceil(Math.random()*20); //生成1-10的随机数
console.log('4s随机数生成的值:',num)
if(num<=10){
resolve(num);
}
else{
reject('4s数字太于10了即将执行失败回调');
}
}, 4000);
})
return p
} Promise
.race([promiseClick3(), promiseClick2(), promiseClick1()])
.then(function(results){
console.log(results);
},function(reason){
console.log(reason);
});

race的使用比如可以使用在一个请求在10s内请求成功的话就走then方法,如果10s内没有请求成功的话进入reject回调执行另一个操作。

ES6异步操作Promise的更多相关文章

  1. ES6的promise对象研究

    ES6的promise对象研究 什么叫promise? Promise对象可以理解为一次执行的异步操作,使用promise对象之后可以使用一种链式调用的方式来组织代码:让代码更加的直观. 那我们为什么 ...

  2. ES6之Promise用法详解

    一 前言 本文主要对ES6的Promise进行一些入门级的介绍.要想学习一个知识点,肯定是从三个方面出发,what.why.how.下面就跟着我一步步学习吧~ 二 什么是Promise 首先是what ...

  3. ES6中promise总结

    一.什么是ES6的Promise 讲太多也没有.直接在打印出来就好,console.dir(Promise) Promise 是一个构造函数,自身有all, reject, resolve 这几个眼熟 ...

  4. ES6新增"Promise"可避免回调地狱

    Promise是一个构造函数,自己身上有all.reject.resolve这几个眼熟的方法,原型上有then.catch等同样很眼熟的方法. 那就new一个 var p = new Promise( ...

  5. 关于ES6的Promise的使用深入理解

    ES6的promise对象研究 什么叫promise? Promise对象可以理解为一次执行的异步操作,使用promise对象之后可以使用一种链式调用的方式来组织代码:让代码更加的直观. 那我们为什么 ...

  6. 解读Es6之 promise

            单线程:  在同一时间只能有同一任务进行.JavaScript就是一门单线程语言                 当有多个任务需要进行时,则需要进行排队,前一个执行完毕才能执行下一个; ...

  7. 教你如何使用ES6的Promise对象

    教你如何使用ES6的Promise对象 Promise对象,ES6新增的一个全新特性,这个是 ES6中非常重要的一个对象 Promise的设计初衷 首先,我们先一起了解一下,为什么要设计出这么一个玩意 ...

  8. ES6的Promise

    推荐一下我觉得不错关于Promise的好文章,通俗易懂 说起ES6的Promise就要提及一下JQ的$.when()方法,两者基本相同 面试的时候经常会问Promise,如果同学们能在回答Promis ...

  9. ES6语法 promise用法

    ES6语法 promise用法 function doSomething(){ return new Promise((resolve,reject)=>{ resolve('jjjj');// ...

随机推荐

  1. nuget安装说明

    1.先百度安装nuget.server 比如 https://www.cnblogs.com/tomfang/articles/3999303.html 2.官网下载nuget.exe nuget p ...

  2. (三)golang--执行流程分析

    XXX.go--go build XXX.go--XXX.exe XXX.go--go run XXX.go 两种方式的区别:(1)如果我们先编译生成了可执行文件,那么我们可以将该可执行文件拷贝到没g ...

  3. ECMAScript 初探 - 对象篇

    一.对象 如果你用过 C++ 或 Java,肯定熟悉类(class).在 ECMAScript 中并没有 "类" 这个词, 其对应的是 "对象定义",不过这太拗 ...

  4. Computing Science CMPT 361

    Computing Science CMPT 361 Fall 2019Assignment #3Due date: November 27th at 11:59 pm.Ray TracingYou ...

  5. Rollup 配置 es6 环境

    前 为了可以使用新型的语法,顺便在兼容下老的浏览器,所以需要自己搭建个环境,目前我个人推崇使用 rollup,主要喜欢它的 tree-shake,打包出来的代码真的很简洁. 配置 rollup.con ...

  6. Axios构造函数学习笔记

    Axios 构造函数 lib/core/axios.js ... var intercaptorManager = require(./IntercaptorManger); var dispatch ...

  7. 元类理解与元类编程 《Python3网络爬虫开发》中第九章代理的使用代码Crawler中代码的理解

    __new__与__init__的理解 __new__()方法是在创建实例之前被调用的,它的作用是创建一个实例,然后返回该实例对象,它是一个静态方法. __init__() 当实例被创建完成之后被调用 ...

  8. IEEE Fellow 何海波

    IEEE Fellow 何海波 11月21日,全球最大的非营利专业技术学会IEEE(电气与电子工程师协会)公布了2018年度新当选Fellow(会士)名单,我校校友何海波教授入选. 何海波,美国罗德岛 ...

  9. Elastic Stack 证书创建

    1.创建CA证书 ./bin/elasticsearch-certutil ca # 默认文件名:elastic-stack-ca.p12 2.生成节点使用的证书 ./bin/elasticsearc ...

  10. DateTime的ToString方法格式

    新建一个.NET Core控制台项目,敲入如下代码: using System; namespace NetCoreDatetime { class Program { static void Mai ...