从零开始学_JavaScript_系列(48)——Promise(1)基础知识
2017-07-28 10:04
501 查看
1、是什么
一个十分适合处理异步操作的对象有进行中(pending)、成功(resolved)、失败(rejected)三种状态
可以轻松处理成功或失败的情况,代码结构更清爽,操作结果可预期
对象的状态不受外界影响,只会根据预先设定的情况执行代码,方便从pending状态切换到resolved或者rejected
Promise对象在创建后会立即执行,但他的then是异步的(即使状态立刻改变,也要等其他代码执行完毕后才会去执行)
Promise对象的状态改变是一次性的,改变后值即确定。不会因为任何情况导致状态反复变化
Promise的状态改变后,会立刻触发其回调函数(执行resolve或者reject)
Promise对象foo可以作为另外一个Promise对象bar的值,并且在foo和bar的状态都不是pending后,才会执行bar的回调
Promise对象的then的值是Promise对象,但和最初的Promise不是同一个
then可以连写,方便连续异步函数的调用
Promise.all可以轻松处理多个异步操作,在全部完成后才应执行的逻辑
Promise.race可以轻松处理多个异步操作,但只需要最快的那个异步操作结果的情况
Promise.resolve和Promise.reject可以轻松将一个变量转为Promise对象并使用
2、基本例子
Promise有几个特点:new出来后立刻执行;
只执行一次,并且结果发生后,无论之后几次调用then,都只执行那唯一一个结果(resolve或者reject);
如果处于pending中,那么执行then时,相当于添加到队列里,pending中不执行,但等结果出来后,会一起执行(而非只执行一个或者不执行);
resolve或者reject只能接受一个参数,如果要传多个参数的话,请使用数组或者对象的形式;
resolve和reject里函数不是在声明时执行,而是异步的,在判定promise的状态为非pending状态时执行;
如以下示例:
console.log(new Date); let foo = new Promise(function (resolve, reject) { setTimeout(function () { //获取毫秒的数值 var d = (new Date()).getMilliseconds(); if (d % 2 === 0) { resolve([new Date(), d]); } else { reject([new Date(), d]); } }, 1000); }) foo.then(function (arr) { console.log(new Date); console.log("resolve: " + arr[0]); }, function (arr) { console.log("reject: " + arr[0]); }) foo.then(function (arr) { console.log(arr[1]); console.log("resolve: " + arr[0]); }, function (arr) { console.log(arr[1]); console.log("reject: " + arr[0]); }) //Tue Jul 04 2017 00:06:52 GMT+0800 (中国标准时间) /* 然后,1秒后 */ //reject: Tue Jul 04 2017 00:06:53 GMT+0800 (中国标准时间) //633 //reject: Tue Jul 04 2017 00:06:53 GMT+0800 (中国标准时间)
以上代码证明了第2,3,4点。而第一点和第五点通过以下代码证明:
let foo = new Promise(function (resolve, reject) { resolve(); console.log("in Promise"); }) console.log("after Promise"); foo.then(function (arr) { console.log("in resolve"); }); console.log("at last"); //in Promise //after Promise //at last //in resolve
证明除了resolve和reject中的代码是异步的之外,其他都是顺序执行(位于foo.then后的代码先执行,之后才执行了foo.then的回调函数)。
3、当两个Promise对象发生交互时
具体来说,Promise实例在执行回调函数时可以传一个参数,而这个参数可以是另外一个Promise实例的回调函数。如代码:let foo = new Promise(function (res, rej) { setTimeout(function () { res("1") }, 1000) }) let bar = new Promise(function (res, rej) { res(foo); //参数是foo实例 })
在这种情况下,bar的回调函数并不会立即执行,而是会等待foo的状态改变后,再去执行bar的回调函数。
即当Promise实例bar的回调函数的参数是另外一个Promise实例foo时,bar在状态改变后不会立即执行,而是等待前一个Promise实例的状态发生改变后,他才会执行。
情况 | foo | bar |
基本情况 | 一个Promise实例 | bar的then的回调函数的参数是foo |
延迟等待时间:foo小于bar | 先执行 | 后执行 |
延迟等待时间:foo大于bar | 先执行 | 等待foo执行完后即执行 |
let foo = new Promise(function (res, rej) { setTimeout(function () { res("1") }, 1500) }) let bar = new Promise(function (res, rej) { setTimeout(function () { console.log(bar); }, 1000) setTimeout(function () { res(foo); }, 500) }) let baz = new Promise(function (res, rej) { res("3"); }) foo.then(function (val) { console.log("foo: " + val); }) bar.then(function (val) { console.log("bar: " + val); }) baz.then(function (val) { console.log("baz: " + val); }) //bar: 3 //状态为"pending" //foo: 1 //bar: 1
如上代码:
bar因为没有延迟,也没有依赖,所以先执行了;
bar虽然500ms后就可以执行,但因为依赖于bar,所以在等待foo执行,注意,此时其状态依然为pending,而不是resolved;
foo在1500ms后执行完毕;
bar发现foo执行完毕了,自己也可以执行,所以跟着执行了;
除此之外,还有几个特点:
作为参数的Promise实例,他会将自己的参数的值传递给另一个Promise实例,即bar的resolve的参数是foo,而foo的resolve的参数的值是”1”,因此bar的resolve的参数的值是”1”;
两个Promise实例要执行的必须都是resolve或者都是reject,不然不会互相影响;
相关文章推荐
- 从零开始学_JavaScript_系列(49)——Promise(2)then、值、catch
- 学习javascript基础知识系列第二节 - this用法
- javascript基础知识系列:eval()
- 前端系列之JavaScript基础知识概述
- 从零开始学_JavaScript_系列(50)——Promise(3)全部完成all和看谁最快race
- 从零开始javascript(1):js基础知识
- 从零开始学_JavaScript_系列(51)——Promise(4)Promise.resolve和Promise.reject
- 学习javascript基础知识系列第三节 - ()()用法
- javascript基础知识系列:DOM学习
- 从零开始学_JavaScript_系列(26)——只需要前端知识的ajax教程
- 通过一段代码学习javascript基础知识系列
- JavaScript知识夯实系列-1.JavaScript基础知识
- JavaScript 设计模式系列:基础知识
- 从零开始学_JavaScript_系列(三)——CSS相关(基础、选择器、position、div)
- 从零开始学_JavaScript_系列(四)——jquery(基础,选择器,触发条件,动画,回调函数)
- JavaScript知识夯实系列-2.基础语法
- 从零开始学_JavaScript_系列(四)——jquery(基础,选择器,触发条件,动画,回调函数)
- 学习javascript基础知识系列第二节 - this用法
- 学习javascript基础知识系列第四节 - 闭包
- 3 HTML&JS等前端知识系列之javascript的基础