ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Promise对象

2021-05-01 12:58:54  阅读:200  来源: 互联网

标签:resolve 对象 Promise result reject new hello


专业英语:

单词释义
promisen. 许诺,允诺;希望
pendingadj. 未决定的;行将发生的
resolvevi. 解决;决心;分解
rejectvt. 拒绝;排斥;抵制;丢弃

Promise概述

  • Promise主要是用来处理异步任务的。
  • 在JS中,promise的含义是“期约”。
  • ECMAScript 6中全局环境中新增了引用类型Promise,可以通过new操作符来实例化。创建新期约时需要传入执行器(executor)函数作为参数。
const promise = new Promise(function(resolve, reject) {
    // code
})
  • 期约对象有两个内部属性,其中[[PromiseState]]表示当前状态,[[PromiseResult]]表示执行结果

Promise对象

  • 期约是一个有状态的对象,可能处于如下三种状态之一:

    • 待定(pending):简单的说,在异步操作中,这就表示操作还未结束;
    • 兑现(fulfilled/resolved):在异步操作中,这表示操作已经结束,且结果为成功;
    • 拒绝(rejected):在异步操作中,这表示操作已经结束,但结果为失败;
  • 待定状态可以转化为兑现状态或者拒绝状态,但这个过程是不可逆的,转换过程由用户传入的执行器控制:

new Promise(function(resolve, reject) {
    // do something
    resolve('hello world');	// 主动调用resolve,将状态转化为兑现(此时它接收一个参数作为执行结果)
})
new Promise(function(resolve, reject) {
    // do something
    reject('hello world');	// 主动调用reject,将状态转化为拒绝(此时它接收一个参数作为执行结果)
})
  • 注意转换是不可逆的,也即转换为兑现或者拒绝后状态就无法再改变:
new Promise(function(resolve, reject) {
    // do something
    resolve();	// 主动调用resolve,将状态转化为兑现
    reject();	// 因为状态已经变成了兑现,所以这里的操作会被静默拒绝(忽略)。
})
  • 状态的转换只能由执行器函数决定,如果我们不主动调用resolve或者reject,那么状态将一直保持为pending

Promise.prototype.then()

  • Promise.prototype.then()是为了给期约实例添加处理程序。then方法最多接收两个函数作为参数:(传给then的任何非函数参数都会被忽略)
new Promise(() => {}).then(onResolved, onRejected);
  • onResolved也即期约转化为兑现时的回调函数onRejected期约转化为拒绝的回调函数。这两个函数都会被传入一个值,那就是期约的执行结果。
  • 当执行器主动调用resolve转化期约状态后,onResolved就会作为回调函数被调用(注意这里resolve不等于onResolved,他们是不同的)。
new Promise(function(resolve, reject) {
    // do something
    resolve('hello world');	// 主动调用resolve,将状态转化为兑现
    console.log('测试点1');
}).then(result => {
    console.log(result);
})

/* 控制台输出:
测试点1
hello wolrd
*/
  • 当执行器主动调用reject转化期约状态后,onRejected就会作为回调函数被调用:
new Promise(function(resolve, reject) {
    // do something
    reject('hello world');	// 主动调用reject,将状态转化为兑现
    console.log('测试点1');
}).then(null, result => {
    console.log(result);
})

/* 控制台输出:
测试点1
hello wolrd
*/
  • then()函数不需要Promise实例化后立即调用,可以在任何时候调用then传递处理程序,而如果在你调用then传递参数时,Promise状态已经发生了转化,有了执行结果,那么你传递的处理程序会立即被执行(这很重要);另外,你也可以多次调用then:
const promise = new Promise(function(resolve, reject) {
    // do something
    resolve('hello world');	// 主动调用reject,将状态转化为兑现
})
setTimeout(function () {
    promise.then(result => console.log('测试点1', result))
    promise.then(result => console.log('测试点2', result))
}, 1000)
/*
测试点1 hello world
测试点2 hello world
*/
  • 此外then()函数也是有返回值的,它会返回一个新的Promise实例,该实例具有如下特征:
    1. 当原实例状态为pending时,这个新实例的状态也会保持为pending
    2. 当原实例状态发生了转化,但我们没有设置对应状态的处理程序(如果状态为resolved,但我们只设置了onRejected,那么也算是未设置处理程序),那么这个新的实例就会使用Promise.resolve()(后面会详细说明)基于原有实例的执行结果重构当前状态。
    3. 在第二种情况下,如果存在对应状态的处理程序,那么新实例就会继续保持pending状态,等待处理程序执行完毕并返回结果,然后使用Promise.resolve()基于该返回值构建新实例。(实际上我也没太弄懂参考书上的描述,结果有点怪异,但从测试结果来看大概是这样的)
    4. 如果原有的Promise实例在执行过程中发送了错误(如状态转化为reject但是我们没有设置onRejected处理函数),那么新实例的状态就会变为rejected,执行结果就是原本实例的执行结果。
console.log(
    new Promise((resolve, reject) => resolve('resolve')).then(),
    new Promise((resolve, reject) => resolve('resolve')).then(result => 'then ' + result),
    new Promise((resolve, reject) => resolve('resolve')).then(undefined, result => 'then ' + result)
);
console.log(
    new Promise((resolve, reject) => reject('reject')).then(),
    new Promise((resolve, reject) => reject('reject')).then(result => 'then ' + result),
    new Promise((resolve, reject) => reject('reject')).then(undefined, result => 'then ' + result)
);

在这里插入图片描述

  • Promise的链式调用与传值现象:利用then的返回值特性,我们可以对Promise对象进行链式调用,并且这其中存在有趣的传值现象
    • 因为then()方法总是会返回一个新的Promise实例对象,而每个实例对象都可以调用then()方法,于是我们可以写成promise.then().then().then()......
    • 根据then()返回值的特点我们可以知道,如果我们没在then()中添加对应状态的处理程序,那么新生成的Promise对象就会继承原来的Promise实例对象的执行结果,这样就会形成层层向后传递的现象,直到某个then()中添加了对应状态的处理程序
new Promise(resolve => resolve('hello')).then().then(result => console.log(result));
// hello
new Promise((resolve, reject) => reject('hello')).then().then(undefined, result => console.log(result));
// hello
new Promise((resolve, reject) => reject('hello'))
    .then(result => console.log('test1', result))
    .then(undefined, result => console.log('test2', result));
// test2 hello
new Promise((resolve, reject) => resolve('hello'))
    .then(result => console.log('test1', result))
    .then(result => console.log('test2', result), result => console.log('test3', result));
// test1 hello
// test2 undefined

Promise.resolve()

  • 该方法是Promise对象上的方法,而不是原型上的方法,因此不会被继承。
  • resolve()方法接收一个参数,然后返回一个Promise实例对象。根据传入参数的不同,返回的Promise实例也会有所区别。
  1. 传入的参数不是对象类型:返回的实例对象状态为兑现(fulfilled/resolved),且执行结果就是我们传入的参数
  2. 传入的参数是一个普通对象:结果与第一种情况一样。
console.log(Promise.resolve('hello world'),
    Promise.resolve(undefined),
    Promise.resolve(null),
    Promise.resolve({test: 'hello'}));

在这里插入图片描述

  1. 传入的参数是Promise实例对象:原封不动的返回这个对象。
  2. 参数是一个含有then()方法的对象:将其中的then()方法作为执行器函数包装成Promise实例对象后返回。
const obj = {
    then(resolve, reject) {
        console.log('then函数被调用');
        resolve('hello world');
    }
}
Promise.resolve(obj).then(result => console.log('测试点', result));
/*
then函数被调用
测试点 hello world
*/

延迟执行 + 链式调用

  • 前不久面试了某大厂的前端实习岗位,其中有一道代码题是让我写出一个obj.print('start').sleep(3000).print('测试点1').sleep(3000).print('end')这样的链式调用的(不能使用队列的方式),且可以延迟执行的对象,当时试了半天也没写出来,于是痛并思痛,决定好好研究一下Promise,现在终于可以轻松搞定了,代码如下:
const timeOutPrint = {
    promise: Promise.resolve(),
    sleep(time) {
        this.promise = this.promise.then(() => new Promise(resolve => setTimeout(resolve, time)))
        return this;
    },
    print(msg) {
        this.promise = this.promise.then(() => console.log(msg));
        return this;
    }
}

timeOutPrint.print('start').sleep(3000).sleep(3000).print('测试点1').sleep(3000).print('end');

标签:resolve,对象,Promise,result,reject,new,hello
来源: https://blog.csdn.net/qq_31444657/article/details/116329427

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有