对于Promise的一些理解

异步在实践开发中无处不在,无论是AJAX还是图片加载,都涉及异步,尽管可以通过回调函数去解决,但是却不够“优雅”。而Promise正是“优雅”的解决方法。Promise的本质是一个对象,可以简单得理解成这个对象有两个属性 status和value, status保存这个Promise的对象的状态,pedding还是fulfilled还是rejectvalue是resolve的参数。状态改变时会调用resolve或者reject。

1.promise实现ajax

定义一个getJSON函数

 getJSON(url) {
        return new Promise(function (resolve, reject) {
            var XHR = new XMLHttpRequest();
            XHR.open('GET', url, true);//这里改一下就是POST了
            XHR.send();
            XHR.onreadystatechange = function () {
                if (XHR.readyState === 4) {
                    if (XHR.status === 200) {
                        try {
                            let response = JSON.parse(XHR.responseText);
                            resolve(response);
                        } catch (e) {
                            reject(e);
                        }
                    } else {
                        reject(new Error(XHR.statusText));
                    }
                }
            }
        })
    }

调用时传入url即可,在then里面的两个函数分别对应resolve和reject

 this.getJSON('https://hq.tigerbrokers.com/fundamental/finance_calendar/getType/2017-02-26/2017-06-10')
        .then((value) => {
            console.log(value)
        },(err) => console.log(err))

 

2.promise实现图片加载

 

以前做项目要做懒加载和预加载,那时候就对图片加载有了比较好的认识,这次也用promise来尝试一下

首先定义一个img标签 img属性设置为空

<img src = {this.state.imgSrc} alt = '图片加载中' />

下面是javascript代码

  loadImage(src) {
        return new Promise((resolve ,reject) => {
            const img = new Image();
            console.log(new Date().getSeconds(),'刚加载')
            img.onload = () => {
                resolve(src)
            }
            img.onerror = () => {
                reject('error')
            }
            img.src = src
        })
    }
 this.loadImage('http://39.108.135.222/upload/8238.jpg')
        .then((src) => {
            console.log(new Date().toISOString(),'加载成功')
            this.setState({imgSrc:src})
        },(err) => {
            console.log(err)
        })

用new Date().toISOString()打印出时间戳 能更好的理解图片异步加载的整个过程

 

3.promise链式调用

这才是promise优雅的原因 链式调用可以让代码有很好的可读性。这里用setTimeout()测试

delay(ms) {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                console.log('延迟了'+ms,'ms')
                resolve(--ms)
            }, ms);
        })
    }
this.delay(1000)
            .then((ms) => this.delay(ms))//这里是return 一个新的promise
            .then(() => console.log('end'))

第二个then调用的是上一个then  return出来的promise

 

4.Promise.all

all接收一个数组参数,里面的值最终都算返回Promise对象。这样,三个异步操作的并行执行的,等到它们都执行完后才会进到then里面。

const promiseArr = ['300','450','620','111'].map((ms ,i) => this.delay(ms))
        Promise.all(promiseArr)//promiseArr中有一个被rejected,Promise.all状态就变成rejected
        .then(()=> console.log('all end'))

同样用上面的delay做测试 当所有的的promise执行完毕,就执行resolve

 

5.Promise与事件循环

我把上面的测试打印出来

不难看出对于 Promise.all里面的promise 是同时执行的

而promise链式调用是顺序执行的

事件循环其实是就是任务队列的执行,任务队列又分为macro-task(宏任务)与micro-task(微任务),例如setTimeout()就是宏任务,而Promise则是微任务

事件循环的顺序,决定了JavaScript代码的执行顺序。它从第一行代码开始第一次循环。执行所有的micro-task。当所有可执行的micro-task执行完毕之后。循环再次从macro-task开始,找到其中一个任务队列执行完毕,然后再执行所有的micro-task,这样一直循环下去。

 

6. 一个封装Promise的函数返回new Promise,Promise.resolve()和new Prmise().then().catch()的区别


    		var func1 = function (aa) {
			return new Promise(function (resolve, reject) {
				setTimeout(function() {
					resolve('data2')
				}, 1000)
			})
			.then(function (value1){
				console.log('value1 : ',value1) //'data2'
				return aa
			})
		}
		func1('tomato').then(function (value) {
			console.log('value2 is :', value) // tomato
		})

new Promise返回当前promise,状态改变时才调用then里面的函数。

Promise.resolve(data)把data变成Promise对象,then立即调用,then中函数的参数值就是Promise.resolve的参数data。

new Prmise().then().catch()如上面例子,已经变成链式调用了。其实返回的还是Promise。

7.个人心得

总而言之,我们可以理解为promise有属性status和value,status保存状态,这个状态是会自动改变的。改变时触发resolve 或reject,一般resolve对应then,reject对应catch。(then也可以传reject,不建议)。then(function(value))里面的value就是promise的属性value。(promise没有value为underfined) 。

promise的value从哪里来呢? Promise.resolve()或者new Promise((resolve,reject) => {resolve(value)}) 

then的返回值,返回的值不是promise对象会自动加上Promise.resolve(returnValue)

 

参考文章 《ES6 标准入门(第3版)》http://es6.ruanyifeng.com/#docs/promise

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值