promise.then返回结果几种情况

Promise是ES6提出的异步编程的新解决方案,旧方案是单纯的使用回调函数。从语法上看,Promise是一个构造函数,既然是构造函数就可以用来对象的实例化,接受一个函数(执行器函数)作为参数,从功能上看,promise对象用来封装一个异步操作,并可以获取其成功/失败的结果值。获取到结果值后,就可以在回调函数中,对结果值进行处理。
---- 异步操作有 ①fs 文件操作 ②数据库操作 ③Ajax ④定时器

一、promise.then返回结果几种情况

首先实例化一个promise对象。promise对象身上有then方法,可用来指定回调,对成功和失败的结果进行处理。它接受两个回调函数,一个是resolve成功的回调,一个是reject失败的回调。

const p = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('成功的回调');
        // reject('失败的回调');
    }, 1000);
});
p.then(value => { }, reason => { });

需要记住的是p.then返回的也是一个promise对象,因此可以进行链式调用。这也是promise可以解决异步编程回调地狱的原因,

重点:then返回的promise对象p1的状态是由then内部回调函数的执行结果来决定的,不取决于p的状态,不取决于你调用的是p的成功或者失败的回调,也就是p1的状态只看回调函数的执行结果。

而回调函数的执行结果有几种情况。如下

1. 如果回调函数的返回结果是 非promise类型的 属性,则then方法返回的promise对象p1的状态为成功fulfilled,同时返回的结果就是promise对象p1成功的值11112222,如下图。需要注意的是,如果你不写return,我们知道函数内部如果不写return默认返回结果是undefined,又undefined也是非promise类型,所以p1状态还是成功fulfilled,返回的promise成功值为undefined。

const p1 = p.then(value => {        //接受p成功的回调
            return '11112222'    
        }, reason => { });
console.log(p1);     //输出p1这个promise对象

        const p1 = p.then(value => { }, reason => {   //接受p失败的回调
            return '33334444'
        });
        console.log(p1);   // 此时p1的状态还是fulfilled,证明只和回调函数的返回结果有关系

  

2.如果回调函数的返回结果是promise对象,则p1的状态就取决于return返回的这个promise对象内部的状态,内部为resolve, 则p1状态为fulfilled,内部为reject,则p1状态为rejected

        const p1 = p.then(value => {
            return new Promise((resolve, reject) => {
                reject('出错了')
            })
        }, reason => { });
        console.log(p1);   //结果为rejected

 

 3.第三种情况为抛出错误,则p1状态为rejected,返回的结果就是你抛出的值

        const p1 = p.then(value => {
            // throw new Error('出错了');
            throw '出错了';    //没有return,直接抛出错误
        }, reason => { });
        console.log(p1);

二、改变promise对象的状态(非then方法中)

实例化一个promise对象,接受一个函数类型的值,里面可以封装异步操作。状态的改变只有两条路,进行中pending变为成功resolved,进行中变为失败rejected,而且只会改变一次,不可能从成功变为失败或者失败变为成功。

只有三种方法改变promise对象的状态,resolve/ reject/ throw抛出错误,如果你在promise对象中不去改变他的状态,那么他的状态永远都是pending,也不会去执行回调函数。

        let p = new Promise((resolve, reject) => {
                resolve('成功数据');    //状态变为 成功resolved
                reject('失败数据');     //状态变为 失败rejected
                throw '报错'             //状态变为 失败rejected
                throw new Error('123');   //状态变为 失败rejected
        })

注意:return并不能改变他的状态,这不是在then方法中,then方法有自己的一套东西。

三、注意点

1、promise对象里面的代码是同步执行的,只是回调函数才是异步执行的,因为你不改变状态就不会去执行回调。而且状态改变后,后续的代码继续执行。

        let p = new Promise((resolve, reject) => {
            console.log(1);
            reject('error');
            console.log(2);
        });

        console.log(3);
        p.catch(reason => {
            console.log(reason);    //最后输出 ‘error’
        });
        console.log(4);
        结果:1 2 3 4 error

2、指定多个回调都会被执行

        let p = new Promise((resolve, reject) => {
            resolve('OK');
        });
        p.then(value => {
            console.log(value);
        });
        p.then(value => {
            console.log(value);
        });
        输出: ok  ok

3、假设你的promise对象,状态变为失败,但是你的then每次只写成功的回调,那就找不到失败的回调,那么他会顺着链一直往下传递,直到找到失败的回调。这就是异常穿透。同理,你的promise对象,状态变为成功,但是你的链只写catch,那就找不到成功的回调,那么他会顺着链一直往下传递,直到找到成功的回调。

三、async/await 

async/await 是ES7提出的基于Promise的解决异步的最终方案。

1、async

async也是一个函数,他和一般的函数不同,他的返回结果是一个promise对象,而且该promise对象的结果是由async函数执行的返回值来决定的,这一点和promise的then的回调函数很像,都是通过返回值来决定状态和结果的。

既然返回promise就可以使用promise的方法,then,catch、finally

        async function main(){
            // 1、 return非promise类型的数据
            return 123;
            // 2、 return的是promise对象
            return new Promise((resolve,reject)=>{
                resolve('success')
                // reject('error')
            }) 
            // 3、抛出异常
            throw '异常'
        }
        console.log(main())    //返回promise对象
        main().then(data=>{
            console.log(data);
        },reason=>{
            console.log(reason);
        })

2、await + 表达式

await必须写在async函数当中,但是async函数中可以没有await。await可以理解为等待,且等到取到值后语句才会往下执行。await其实说白了就是对promise对象的成功结果进行获取,如果失败就通过catch获取失败的结果。
await的右侧的表达式一般都是promise对象,但也可以是其他值
一、如果表达式是promise对象并且状态为成功,那么await将返回的是这个promise对象成功的值;
二、如果表达式是promise对象,并且它失败了,那么就要通过try,catch进行捕获错误,不捕获错误那么后面代码无法执行。
三、如果不是Promise对象,把这个非promise的东西当做await表达式的结果,如字符串数字等。

async function main(){
            let p1 = new Promise((resolve,reject)=>{
                resolve('success')
            })
            let p2 = new Promise((resolve,reject)=>{
                reject('error')
            })
            // 1、右侧为promise情况,常用
            let res1 = await p1;
            console.log(res1);    // success
            // 2、右侧为promise情况,并且失败了,失败了没有通过 trycatch 捕获,那后面代码就不会执行了
            try {
                let res2 = await p2;
            } catch (e) {
                console.log(e);
            }
            // 3、右侧为非promise类型的数据
            let res3 = await 123;
            console.log(res3);   // 123
        }
        main()

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值