首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ES6(二):Promise

ES6(二):Promise

作者头像
从入门到进错门
发布2018-12-14 15:12:41
4160
发布2018-12-14 15:12:41
举报

版权声明:本文为博主原创文章,未经博主允许不得转载。

ES6之前解决异步编程只能使用回调函数或事件,ES6中加入了 Promise,使得异步编程更加简洁直观和合理

特点

Promise是一个对象,具有以下两个特点:

  • 对象的状态不受外界影响
  • 状态一旦改变就不会再变

使用方法

基本使用

ES6中规定,Promise对象是一个构造函数,于是我们就需要使用new关键字实例化:

code:

const promise = new Promise((resolve, reject) => {
    if (true) {
        resolve(successRes);
    } else {
        reject(errorText);
    }
});

Promise接受一个函数作为参数,该函数的两个参数分别是:resolvereject。其中:

resolve可以表示异步操作成功时调用 reject则可以表示异步操作失败时调用

then

Promise实例生成之后,可以使用then方法分别指定成功和失败状态的回调函数。例如:

code

let a = 10;
const promise = new Promise((resolve, reject) => {
    if (a === 10) {
        resolve('成功!');
    } else {
        reject('失败!');
    }
});
promise.then((res) => {
    console.log(res); // 成功!
}, (err) => {
    console.log(err);
});
let a = 0;
const promise = new Promise((resolve, reject) => {
    if (a === 10) {
        resolve('成功!');
    } else {
        reject('失败!');
    }
});
promise.then((res) => {
    console.log(res);
}, (err) => {
    console.log(err); // 失败!
});

当然,then的第二个参数并不是必须的,大部分时候我们其实都只需要第一个参数(成功),而失败的回调可以放在catch中去执行。

catch

比如上面返回‘失败’的例子,我们可以使用catch进行改造:

code

let a = 10;
const promise = new Promise((resolve, reject) => {
    if (a === 10) {
        resolve('成功!');
    } else {
        reject('失败!');
    }
});
promise.then((res) => {
    console.log(res);
}).catch((err) => {
    console.log(err); //失败!
});

大部分时候我们都是这样使用的

Ajax实例

我们可以使用Promise对象实现一个ajax实例,这也是Promise用处最广的地方:

code

const myAjax = function(data, url) {
    const promise = new Promise((resolve, reject) => {
        const stateChange = function() {
            if (this.readyState !== 4) {
                return;
            }
            if (this.status === 200) {
                resolve(this.response);
            } else {
                reject(new Error(this.statusText));
            }
        };
        const myHttp = new XMLHttpRequest();
        myHttp.open('GET', url, 'true');
        myHttp.onreadystatechange = stateChange;
        myHttp.responseType = 'json';
        myHttp.setRequestHeader('Accept', 'application/josn');
        myHttp.send(data);
    });
    return promise;
};

myAjax('/uuurl').then(res => {
    console.log(res);
}).catch(err => {
    console.log(err);
});

其他特性

新建就会立即执行

code

const promise = new Promise(function(resolve, reject) {
    console.log('我是resolve之前的打印');
    resolve();
});
  
promise.then(function() {
    console.log('我是成功的回调的打印');
});
  
console.log('我是最外层的打印');

// 结果:
// 我是resolve之前的打印
// 我是最外层的打印
// 我是成功的回调的打印

结果和我们想象的一致,先是打印resolveconsole,因为Promise一建立就会执行,而后进行的是最外层的打印,那是因为then指定的回调函数将在当前脚本所有同步任务执行完之后才会执行。

一个异步操作的结果是返回另一个异步操作

通常情况下,reject函数的参数是Error对象的实例,表示抛出的错误;而resolve函数的参数除了正常的值以外,还可能是另一个Promise实例: code

const pro1 = new Promise((resolve, reject) => {

});
const pro2 = new Promise((resolve, reject) => {
    resolve(pro1);
});

上述代码中,pro1pro2都是Promise实例,但是pro2resolvepro1作为参数,此时pro1的状态就会传递给pro2,也就是说,pro1的状态决定了pro2的状态。 这一点从以下代码可以很直观的看出来: code

const pro1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        return reject(new Error('err'));
    }, 3000);
});
const pro2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        return resolve(pro1);
    }, 1000);
});

pro2.then(res => {
    console.log(res);
}).catch(err => {
    console.log(err);
});

在这段代码中,pro1是一个Promise对象,并且在3秒之后返回Error的实例errpro2的状态则是在1秒之后改变。由于pro2返回的是另一个Promisepro1),导致pro2自己的状态无效了,由pro1的状态决定pro2的状态。所以最终输出的结果是:

过了3秒输出Error:err

调用resolvereject并不会终结Promise的参数函数的执行

先来看一段代码: code

const proromise = new Promise((resolve, reject) => {
    resolve('ok');
    console.log('我是resolve后面的代码');
});

proromise.then(res => {
    console.log(res);
});

// 结果:
// 我是resolve后面的代码
// ok

和预想的一样,虽然先调用了resolve('ok');,但是后面的代码还是会执行,并且会先打印出来,这是因为调用resolvereject并不会终结Promise的参数函数的执行,而且then指定的回调函数将在当前脚本所有同步任务执行完之后才会执行。一般调用resolvereject之后Promise的任务就完成了,所以建议在resolvereject之后加上return

参考链接

《ECMAScript 6 入门》——阮一峰 ECMAScript® 2015 Language Specification ECMAScript® 2016 Language Specification ECMAScript® 2019 Language Specification

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年11月21日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 特点
  • 使用方法
    • 基本使用
      • then
        • catch
        • Ajax实例
        • 其他特性
          • 新建就会立即执行
            • 一个异步操作的结果是返回另一个异步操作
              • 调用resolve或reject并不会终结Promise的参数函数的执行
              • 参考链接
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档