异步编程–Promise的用法

异步编程–Promise的用法

阅读Promise的简单实现https://blog.csdn.net/jl244981288/article/details/47166183

console.dir(Promise)--浏览器控制台查看Promise对象

目录

Promise简介

Promise的出现实际上是为了解决回调地狱的问题,在正式理解Proise的用法之前我们先来了解下什么是回调方法,看下面一段代码:

function foo(arg1, callback) {
    if(arg1>5 && typeof callback === 'function') {
        callback();
    }
}

foo(10, function() {
     console.log('我来自回调函数')
});

上面的foo函数传入的第二个参数是一个函数,当满足某种条件的时候,程序再来执行传入的这个函数,这就是一个典型的回调函数的用法。 
理解了上面回调函数的用法后我们再来看一个Promise的用法:

var p = new Promise(function(resolve, reject) {
    setTimeout(function() {
        resolve('我来自回调函数');
    }, 3000);
});

p.then((value) => {
     console.log(value)
});

代码中用new关键字实例化了一个Promise对象,在Promise的构造函数中传入了一个函数,这个函数分别传入resolve和reject两个参数,分别表示异步操作执行“成功”和执行“失败“”的情况下的回调函数,这里的“成功”和“失败”描述的不够准确,实际上应该对应着promise的fulfill和reject两个状态。

接着我们在Promise返回的对象上调用了then方法,then方法接收了两个参数,运行这段代码,3秒后会在控制台输出“我来自回调函数”。看到这里大家可能已经明白了,promise其实就是跟回调是一个意思。

Promise的应用一:处理多个相互依赖的异步请求

我们在开发的过程中肯定遇到过这样的问题,调用一个ajax请求A拿到一些数据,再根据请求A中的某些数据去请求另一个ajax接口B去查询数据,如果我们使用Promise写法应该如何解决这个问题呢?请看下面的代码:

function a(){
    return new Promise(function(resolve, reject) {
        $.ajax({
          url:"/url1",
          type: "GET",
          async:true,
          dataType:"json",
          success:function(data){
              resolve(data);
          }
        })
    });
}

function b(id){
    return new Promise(function(resolve, reject) {
        $.ajax({
            url:"/url2",
            type: "POST",
            async:true,
            data:id,
            dataType:"json",
            success:function(data){
              resolve(data);
            }
        })
    });
}

$("#btn").click(function() {
    a().then(function (data) {
        b(data.id);
    }).then(function(response) {
        console.log(response);
    });
})

上面的代码我们可以看到,通过Promise的链式调用,避免了嵌套调用时代码过于冗长的问题。

Promise的应用二:并行执行多个异步请求

Promise的all方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后才执行回调,注意,当所有异步执行的Promise任务都变为resolve时,该方法才会返回。看一个例子:

扫描二维码关注公众号,回复: 2730101 查看本文章
var p1 = new Promise(function(resolve, reject) {
    setTimeout(() => {
        resolve('异步任务1');
    }, 3000);
});
var p2 = new Promise(function(resolve, reject) {
    setTimeout(() => {
        resolve('异步任务2');
    }, 2000);
});
var p3 = new Promise(function(resolve, reject) {
    setTimeout(() => {
        resolve('异步任务3');
    }, 1000);
});

Promise.all([p1,p2,p3]).then((value) => {
    console.log(value); // 打印['异步任务1','异步任务2','异步任务3']
});

上面的代码在控制台中打印的结果是[‘异步任务1’,’异步任务2’,’异步任务3’]。我们可以看到,p1对象中的setTimeout是3秒,p2对象中的setTimeout是2秒,p3对象中的setTimeout是1秒,但是在Promise.all方法中输出的结果依然会按照Promise对象传入数组中的顺序返回结果。

Promise的应用三:Promise.race的应用

Promse.race的方法和Promise.all方法有些类似。Promise.all方法是谁跑的慢,以谁为准执行回调,Promise.race相反,是谁跑的快,以谁为准执行回调。基与上面的代码进行示例:

Promise.race([p1,p2,p3]).then((value) => {
    console.log(value); 
});

代码执行的结果是,输出’异步任务3’,’异步任务2’,’异步任务1’。可能跟你想的不完全一致对吧?在then里面的回调开始执行时,在p3输出结果后 p2和p1并没有停止输出,而是将所有结果都输出完为止。 
Promise的race方法有什么用呢?使用场景还是很多的,比如我们可以用race给某个异步请求设置超时时间,并且在超时后执行相应的操作,代码如下:

//异步请求某个资源
function getSomething() 
    let p = new Promise(function(resolve, reject) {
        let img = new Image();
        img.onload = function() {
            resolve(img);
        }
        img.src = 'test';
    });
    return p;
}

//延时函数,用于给请求计时
function timeOut() {
    let p = new Promise(function(resolve, reject) {
        setTimeout(() => {
            reject('资源请求超时');
        }, 10000);
    });
    return p;
}

Promise
.race([getSomething(), timeOut()])
.then((resource) => {
    console.log(resource);
})
.catch((error) => {
    console.log(error);
});

getSomething函数会进行一个异步请求,timeOut函数是一个延时10秒的异步操作。我们把这两个返回Promise对象的函数放进race,看他们两先执行完成,如果10秒之内资源请求成功了,则执行resolve方法,资源成功请求。如果10秒之内资源没有成功请求到,那么timeOut就要先执行,则进入catch,抛出“资源请求超时”的异常。

猜你喜欢

转载自blog.csdn.net/wenmin1987/article/details/81608392