ES6中Promise的用法小结

promise是什么?

 回调函数真正的问题在于他剥夺了我们使用 return 和 throw 这些关键字的能力。而 Promise 很好地解决了这一切。
 1. 主要用于异步计算
 2. 可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果
 3. 可以在对象之间传递和操作promise,帮助我们处理队列

语法:

	new Promise( function(resolve, reject) 
		{...} /* executor */  
	);

  executor是带有 resolvereject 两个参数的函数 。Promise构造函数执行时立即调用executor 函数, resolve 和 reject 两个函数作为参数传递给executor(executor 函数在Promise构造函数返回所建promise实例对象前被调用)。

创建Promise:

  Promise 对象是由关键字 new 及其构造函数来创建的。该构造函数会把一个叫做“处理器函数”(executor function)的函数作为它的参数。这个“处理器函数”接受两个函数——resolve 和 reject ——作为其参数。当异步任务顺利完成且返回结果值时,会调用 resolve 函数;而当异步任务失败且返回失败原因(通常是一个错误对象)时,会调用reject 函数

	const myFirstPromise = new Promise((resolve, reject) => {
	  // ?做一些异步操作,最终会调用下面两者之一:
	  //
	  //   resolve(someValue); // fulfilled
	  // ?或
	  //   reject("failure reason"); // rejected
	});

想要某个函数拥有promise功能,只需让其返回一个promise即可。

	function myAsyncFunction(url) {
	  return new Promise((resolve, reject) => {
	    const xhr = new XMLHttpRequest();
	    xhr.open("GET", url);
	    xhr.onload = () => resolve(xhr.responseText);
	    xhr.onerror = () => reject(xhr.statusText);
	    xhr.send();
	  });
	};

  Promise 对象的两个特点
  (1)对象的状态不受外界影响。Promise 对象代表一个异步操作,有三种状态:Pending(进行中)、Resolved(已完成,又称 Fulfilled)和 Rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是 Promise 这个名字的由来,它的英语意思就是「承诺」,表示其他手段无法改变。

  (2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise 对象的状态改变,只有两种可能:从 Pending 变为 Resolved 和从 Pending 变为 Rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。就算改变已经发生了,你再对 Promise 对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

  有了 Promise 对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise 对象提供统一的接口,使得控制异步操作更加容易。

  Promise 也有一些缺点。首先,无法取消 Promise,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部。第三,当处于 Pending 状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。

	var promise = new Promise(function(resolve, reject) {
		if (/* 异步操作成功,抛出状态 */){
			resolve(value);
		} else {
			reject(error);
		}
	});
	
	promise.then(function(value) {
		// success
	}, function(value) {
		// failure
	});

  Promise 构造函数接受一个函数作为参数,该函数的两个参数分别是 resolve 方法和 reject 方法。

  如果异步操作成功,则用 resolve 方法将 Promise 对象的状态,从「未完成」变为「成功」(即从 pending 变为 resolved);
  如果异步操作失败,则用 reject 方法将 Promise 对象的状态,从「未完成」变为「失败」(即从 pending 变为 rejected)。

resolved 这是一个正常的已决阶段下的状态,后续处理为thenable
rejected 这是一个非正常的已决阶段下的状态,后续处理为catchable

注意: 如果一个promise对象处在fulfilled或rejected状态而不是pending状态,那么它也可以被称为settled状态。你可能也会听到一个术语resolved ,它表示promise对象处于settled状态。关于promise的术语, Domenic Denicola 的 States and fates 有更多详情可供参考。

方法

  1. Promise.all(iterable)
      这个方法返回一个新的promise对象,该promise对象在iterable参数对象里所有的promise对象都成功的时候才会触发成功,一旦有任何一个iterable里面的promise对象失败则立即触发该promise对象的失败。

    	const proms = [];
        for (let i = 0; i < 10; i++) {
            proms.push(new Promise((resolve, reject) => {
                setTimeout(() => {
                    if (Math.random() < 0.9) {
                        console.log(i, "成功");
                        resolve(i);
                    } else {
                        console.log(i, "失败")
                        reject(i);
                    }
                })
            }))
        }
        const pro = Promise.all(proms);
        pro.then(data => {
            console.log("全部成功", data)
        }, err => {
            console.log("有失败的", err)
        })
        //只有生成的随机数全部小于0.9的时候,才会推出resolve成功状态,并输出“全部成功”,否则输出“有失败的”
    
  2. Promise.race(iterable)
      当iterable参数里的任意一个子promise被成功或失败后,父promise马上也会用子promise的成功返回值或失败详情作为参数调用父promise绑定的相应句柄,并返回该promise对象。

        function getRandom(min, max) { //promise完成时间
            return Math.floor(Math.random() * (max - min) + min);
        }
        const proms = [];
        for (let i = 0; i < 10; i++) {
            proms.push(new Promise((resolve, reject) => {
                setTimeout(() => {
                    if (Math.random() < 0.5) {
                        console.log(i, "成功")
                        resolve(i)
                    } else {
                        console.log(i, "失败")
                        reject(i)
                    }
                }, getRandom(1000, 5000))
            }))
        }
        const pro = Promise.race(proms)
        pro.then(data => {
            console.log("有promise完成", data)
        }, err => {
            console.log("有promise失败的", err)
        })
        //只要有一个成功的状态则立即推出这个状态,并调用对应的处理函数
    
  3. allSettled()
      等到所有promises都完成(每个promise返回成功或失败)。
      返回一个promise,该promise在所有promise完成后完成。并带有一个对象数组,每个对象对应每个promise的结果。

      const promise1 = Promise.resolve(3);
      const promise2 = new Promise(function(resolve, reject) {
          setTimeout(reject, 100, 'foo')
      });
      const promises = [promise1, promise2];
    
      Promise.allSettled(promises).
      then(function(results) {
          results.forEach(function(result) {
              console.log(result.status)
          })
      });
      // 输出 fulfilled  
      // 输出 rejected
    
  4. reject()方法返回一个带有拒绝原因的Promise对象。
      静态函数Promise.reject返回一个被拒绝的Promise对象。通过使用Error的实例获取错误原因reason对调试和选择性错误捕捉很有帮助。

    	Promise.reject(new Error('fail')).then(function() {
    	  // not called
    	}, function(error) {
    	  console.error(error); // 输出: Error: fail
    	});
    
  5. resolve() 方法返回一个以给定值解析后的Promise 对象。
      如果这个值是一个 promise ,那么将返回这个 promise ;如果这个值是thenable(即带有"then" 方法),返回的promise会“跟随”这个thenable的对象,采用它的最终状态;否则返回的promise将以此值完成。

        const promise1 = Promise.resolve(123);
      	promise1.then((value) => {
            console.log(value);//输出:123
        });
        // 或者下面写法
        const promise1 = Promise.resolve(123).then(
        function(value) {
        	console.log(value); //输出:123
    	}, function(value) {//当Promise推出的是reject状态时调用 
        	// 不会被调用
    	});
    

个人总结:

有六个注意点:
  1.未决阶段下的处理函数是同步的,会立即执行。
  2. thenable和catchable函数是异步的,就算会立即执行,也会加入等待队列中的微任务。

    const pro = new Promise((resolve, reject) => {
        console.log("a");
        reject(123)
        setTimeout(() => {
            console.log("b");
        })
    })
    pro.then(data => {
        console.log(data);
    })
    pro.catch(err => {
        console.log(err);
    })
    console.log(c);
    //输出: a
    //报错: c is not defined
    //输出:123
    //输出:Uncaught (in promise) 123
    //输出:b

  3.pro.then方法可以写thenable和catchable函数,而pro.catch方法只能写catchable函数。
  在未决状态的处理函数中,如果发生未捕获的错误,则会将状态推向rejected中, 并且会被catchable所捕获。

    const pro = new Promise((resolve, reject) => {
        throw new Error("123"); //未捕获的错误,所以进入catch中
    })
    pro.then(data => {
        console.log(data)
    }, err => {
        console.log(err)
    });
    // 报错:Error: 123
	或者换种写法
	pro.catch(err => {
        console.log(err); //输出 Error: 123
    })

  4.一旦状态推向已决阶段,无法做任何改变。

	const pro = new Promise((resolve, reject) => {
	//resolve与reject只能存在一个, 多个无效, 采取第一次的值
        resolve(123)
        reject(456)
    })
    pro.then(data => {
        console.log(data);
    })
    pro.catch(err => {
        console.log(err);
    })
    //输出:123
    
	或者:
	
	const pro = new Promise((resolve, reject) => {
        //resolve与reject只能存在一个, 多个无效, 采取第一次的值
        throw new Error("123") //未捕获
        reject("1564653");
        try {
            throw new Error("456") //已捕获
        } catch (e) {
            console.log(e)
        }
        resolve(123)
        reject(456)
    })
    pro.then(data => {
        console.log(data);
    })
    pro.catch(err => {
        console.log(err);//返回 Error: 123
    })
    上面已经发生了未捕获的错误,已经传值catch中,后面又进行了一次赋值,无法改变,只能保持第一次的值

  5.如果前面的promise的后续处理,返回的是一个promise对象,则返回的promise状态和后续处理返回的promise状态保持一致。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值