js异步(一)Promise 理解总结

在js学习过程中对js中的各种异步进行一个个人的总结

Promise使用原因

因为JavaScript是单线程,在Promise未出现之时如果想要实现异步操作,最常用的方法是使用回调函数,在有很多层回调时就会陷入回调地狱,使得代码变得难以阅读和维护。Promise的出现正是为了解决这个问题,将异步过程和对结果的处理分离。本质上,Promise 是一个绑定了回调的对象,而不是将回调传进函数内部。

Promise基本用法

function timeout(n) {
    return new Promise((resolve, reject) => {
        // 一些异步操作
        setTimeout(() => {
            // 异步操作成功后执行
           resolve('timeout Promise'); 
        }, n)
        
        // 异步操作失败后执行
        reject('timeout failed');
    })
}

timeout(1000)
    .then(result => {
        console.log(result);
    }, error => {
        console.log(error);
    });

// timeout Promise

Promise构造函数接受一个有两个参数的函数作为参数,resolve为异步操作执行成功后的处理函数,参数为想要向处理函数传递的参数,reject为异步操作失败时执行的函数。

Promise三种状态

  • pending (初始化/待定,尚未执行或拒绝)
  • resolved(已执行,与 promise 相关的操作成功)
  • rejected(已拒绝,与 promise 相关的操作失败)

resolve函数将Promise对象的状态从 pending 变为 resloved,reject函数将Promise对象的状态冲 pending 变为 rejected。Promise 实例生成后,可以用then方法可以指定resolve和reject函数,它的第一个参数为resolve函数,第二个参数为reject函数,其中第二个参数可选,也可以将第二个参数拿出来作为catch(二者区别相见错误处理部分)

timeout(1000)
    .then(result => {
        console.log(result);
    }).catch( error => {
        console.log(error);
    })
  • Promise 只能成功或失败一次,不能成功或失败两次,已不能从成功转为失败或从失败转为成功

相当于一个状态机,只能从 pending 转为 resloved/rejected,一旦修改就不能改变,而且执行了一个就不会继续执行下一个了,之前的例子中,setTimeout成功之后,即使写了reject('timeout failed')也不会执行。

调用时间

首先改一下之前的代码

function timeout(n) {
    return new Promise((resolve, reject) => {
        console.log('new Promise');

        // 一些异步操作
        setTimeout(() => {
           resolve('timeout Promise'); 
        }, n)

        reject('timeout failed');
    })
}

timeout(1000)
    .then(result => {
        console.log(result);
    }).catch( error => {
        console.log(error);
    });

console.log('after timeout');

// new Promise
// after timeout
// timeout Promise

Promise 属于任务队列中的微任务,根据JavaScript事件循环,Promise在新建后立即执行,而 then 函数指定的回调函数在当前脚本所有同步任务执行完才会执行。

链式调用

then 函数中可以仍旧返回一个 Promise 对象,实现链式操作

function timeout(n) {
    return new Promise((resolve, reject) => {
        // 一些异步操作
        setTimeout(() => {
           resolve(n + 200); 
        }, n)
    })
}

// 链式调用
const time1 = 500;
timeout(time1)
    .then(time2 => {
        console.log(time1, time2);
        return timeout(time2).then( time3 => [time1, time2, time3]);
    })
    .then(times => {
        const [time1, time2, time3] = times;
        console.log(time1, time2, time3);
        return timeout(time3);
    })
    .then(result => {
        console.log('result', result);
    })

// 500 700
// 500 700 900
// result 1100

注:一定要有返回(即 return),否则 callback 无法获取上一个 Promise 的结果。

错误处理

使用 catch 可以在一个回调失败后继续使用链式操作  

new Promise((resolve, reject) => {
    console.log('initial');
    resolve();
})
.then(() => {
    throw new Error('Something failed');
    console.log('do this');
})
.catch(() => {
    console.log('do that');
})
.then(() => {
    console.log('do this whatever happened before');
})

// initial
// do that
// do this whatever happened before

 

如果写成 then( func1, func2)形式,则 func1 或 func2 中的一个将被调用,而不会二者均被调用,但如果是 then( func1 ).catch( func2 )形式,则在 func1 拒绝时两者均被调用。

 

参考:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值