5分钟快速弄懂Promise

目录

前言

Promise的基本用法

封装ajax的请求

Promise中常见的误区

Promise并行执行


前言

回调函数可以说是Javascript中异步编程的根基,如果我们使用传统的方法去实现复杂的异步过程,就会很容易形成回调地狱,实现起来非常不优雅而且比较难维护。那么,有没有一种能解决这种问题呢?答案是肯定的。ES2015提供了一种规范,用来解决这种问题,这种规范就叫Promise。

Promise的基本用法

promise接受一个函数,这个函数接受

两个参数,一个是成功的resovle,另一个是失败的reject。

const promise = new Promise(function (resolve, reject) {
    resolve("成功");
    //reject("失败");
})
promise.then(function (value) {
    console.log("resolve", value);  //resolve 成功
}, function (error) {
    console.log("reject", error);
})

上例中,我们调用promise的then方法,该方法有两个参数,第一个对应的是上面定义的resolve方法,我们可以在里面实现成功时候的方法,第二个对应的是上面定义的reject方法,我们可以在里面实现失败后的方法。需要注意的是,我们定义Promise时传入的两个参数中,只有一种结果,要么是成功,要么是失败。如下图展示:

const promise1 = new Promise(function (resolve, reject) {
    resolve("成功");
    reject("失败");
})
promise1.then(function (value) {
    console.log("resolve", value)  // resolve 成功
}, function (error) {
    console.log("reject", error);  // 不执行
})

const promise2 = new Promise(function (resolve, reject) {
    //resolve("成功");
    reject("失败");
})
promise2.then(function (value) {
    console.log("resolve", value)    // 不执行
}, function (error) {
    console.log("reject", error);  // reject 失败
})

封装ajax的请求

我们可以使用Promise来封装ajax的请求,定义一个方法,该方法返回一个Promise。

function ajax (url) {
    return new Promise(function (resolve,reject ) {
        var xhr = new XMLHttpRequest();
        xhr.open('GET', url);
        xhr.responseType = 'json';
        xhr.onload = function () {
           if(this.status === 200) {
               resolve(this.response);
           } else {
               reject(new Error(this.statusText));
           }
        }
        xhr.send();
    })
}

ajax("XXXX").then(function (res) {
    console.log(res);
}, function (error) {
    console.log(error);
})

Promise中常见的误区

使用Promise中有个常见的误区,就是嵌套使用,例如当我们请求3依赖于请求2的结果,而请求2又依赖于请求1......如此,我们可能会这样写:

ajax('api/users').then(function (user1) {
    ajax(user1).then(function (user2) {
        ajax(user2).then(function (user3) {
            ajax(user3).then(function () {
                
            })
        })
    })
})

这样写是错误的。这时,我们可以利用promise的链式调用,实现扁平化。需要注意的是:

  • Promise对象的then方法会返回一个全新的Promise对象
  • 后面的then方法就是在为上一个then返回的Promise注册回调
  • 前面then方法中回调函数的返回值会作为后面then方法回调的参数

链式调用的使用方法,异常的捕获建议采用catch方式。如下:

ajax('api/users').then(function (value) {
   console.log('resolve',value);
   return ajax('/error-url');
}).catch(function (error) {
    console.log("error",error);
})

Promise并行执行

var promiseAll = Promise.all([
    ajax('请求1'),
    ajax('请求2')
])

promiseAll.then(function (values) {
    console.log(values);       //返回的结果是一个数组,两个请求都成功才返回,其中一个失败则不返回
    console.log(values[0]);   //请求1结果
    console.log(values[1]);   //请求2结果
}).catch( function (error) {
    console.log(error);     
})

最后补充一点,Promise的执行顺序属于微任务,优先于setTimeout的执行。

 

你可能感兴趣的:(JavaScript)