JS:异步编程-promise

promise对象

(1)概述

  • promise是异步编程的一种解决方案。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。

  • Promise 异步操作有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。除了异步操作的结果,任何其他操作都无法改变这个状态。

  • Promise 对象只有:从 pending 变为 fulfilled 和从 pending 变为 rejected 的状态改变。只要处于 fulfilled 和 rejected ,状态就不会再变了即 resolved(已定型)。

  • Promise是一个构造函数,其原型上有then、catch方法,对象上有reject、resolve方法。

同步的设计思想

            function createData(){
                return parseInt((Math.random()*(90-50)+50));
            }
            var obj={
                data:100,
                tool:function(){
                   
                    var data=createData();
                    this.data=data  ;                
                }
            }          
            obj.tool();
            console.log(obj.data);
异步的设计思想-回调函数

 

            function createData(callback) {
                callback(parseInt((Math.random() * (90 - 50) + 50)));
            }


            var obj = {
                data: 100,
                tool: function() {
                    var a = 20;
                    createData((n) => {
                        this.data = n;
                    })
                    var b=100;
                    for(;;){}
                }
            }
            obj.tool();
            console.log(obj.data);
          
    
异步函数:
       function fn (cb,n) { for(var i=0;i<n;i++){} cb(); } console.log(1); fn(function(){console.log(3)},10000);//这个函数内部也有一个打印 3 console.log(5); // fn函数不可能是异步函数 但是js的底层 c/c++有不阻塞代码的异步函数 setTimeout(function(){console.log(4)},1000); console.log(2);
 
(2)官方提供的非阻塞异步函数:
setTimeout()函数是一个非阻塞的异步函数
then函数也是一个非阻塞的异步函数
setTimeOut(function(){console.log(2)});

 

thencatch方法:

runAsync().then(function(data){
    console.log(data);
    //后面可以用传过来的数据做些其他操作
    //......
});

 

在runAsync()的返回上直接调用then方法,then接收一个参数,是函数,函数的参数data将会拿到我们在runAsync中调用resolve时传的的参数。

此时then里面的函数就是回调函数,能够在runAsync这个异步任务执行完成之后被执行。这就是Promise的作用了,简单来讲,就是能把原来的回调写法分离出来,在异步操作执行完后,用链式调用的方式执行回调函数。

then:

then函数的返回值是 一个新的promise对象,是then传入的回调函数的返回值:

  1. 如果是一个promise对象 那么就是它
  2. 如果不是一个promise对象,那么就会把函数的结果包装为一个生成数据了的promise对象

 

catch的用法

我们知道Promise对象除了then方法,还有一个catch方法,它是做什么用的呢?其实它和then的第二个参数一样,用来指定reject的回调,用法是这样:

getNumber()
.then(function(data){
    console.log('resolved');
    console.log(data);
}).catch(function(reason){
    console.log('rejected');
    console.log(reason);
});

 

效果和写在then的第二个参数里面一样。不过它还有另外一个作用:在执行resolve的回调(也就是上面then中的第一个参数)时,如果抛出异常了(代码出错了),那么并不会报错卡死js,而是会进到这个catch方法中。

getNumber()
.then(function(data){
    console.log('resolved');
    console.log(data);
    console.log(somedata); //此处的somedata未定义
})
.catch(function(reason){
    console.log('rejected');
    console.log(reason);
});

在resolve的回调中,我们使用了console.log(somedata);而somedata这个变量是没有被定义的。如果我们不用Promise,代码运行到这里就直接在控制台报错了,不往下运行了。但是在这里,会得到这样的结果:

也就是说进到catch方法里面去了,而且把错误原因传到了reason参数中。即便是有错误的代码也不会报错了,这与我们的try/catch语句有相同的功能。

执行ajax请求的结构代码:

 

 

 

 

 
*Promise主动产生数据 不用给它添加数据  而是它自己产生数据
 

(3)reject的用法

事实上,我们前面的例子都是只有“执行成功”的回调,还没有“失败”的情况,reject的作用就是把Promise的状态置为rejected,这样我们在then中就能捕捉到,然后执行“失败”情况的回调。

function getNumber(){
    var p = new Promise(function(resolve, reject){
        //做一些异步操作
        setTimeout(function(){
            var num = Math.ceil(Math.random()*10); //生成1-10的随机数
            if(num<=5){
                resolve(num); //执行成功
            }
            else{
                reject('数字太大了'); //执行失败
            }
        }, 2000);
    });
    return p;            
}
​
getNumber()
.then(
    function(data){
        console.log('resolved');
        console.log(data);
    }, 
    function(error, data){
        console.log('rejected');
        console.log(error);
    }
);

 

getNumber函数用来异步获取一个数字,2秒后执行完成,如果数字小于等于5,我们认为是“成功”了,调用resolve修改Promise的状态。否则我们认为是“失败”了,调用reject并传递一个参数,作为失败的原因。

运行getNumber并且在then中传了两个参数,then方法可以接受两个参数,第一个对应resolve的回调,第二个对应reject的回调。所以我们能够分别拿到他们传过来的数据。多次运行这段代码,随机得到下面两种结果:

 

 

 

 

posted on 2022-07-14 16:15  香香鲲  阅读(233)  评论(0编辑  收藏  举报