前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >javascript之Promise对象知识点整理

javascript之Promise对象知识点整理

作者头像
山行AI
发布2019-07-25 15:44:09
5930
发布2019-07-25 15:44:09
举报
文章被收录于专栏:山行AI

Promise对象是CommonJS工作组为异步编程提供的统一接口,是ECMAScript6中提供了对Promise的原生支持,Promise就是在未来发生的事情,使用Promise可以避免回调函数的层层嵌套,还提供了规范更加容易的对异步操作进行控制。提供了reject,resolve,then和catch等方法。

Promise规范https://promisesaplus.com/中对Promise的状态的定义:

Promise 是一个对象。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败),只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。其状态改变只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了。

  • 执行完resolve,状态就变成fulfilled;
  • 执行完reject,状态就变成rejected;
  • 只要状态改变过(执行过resolve)就会执行回调函数,不用担心因为提供回调函数过晚,而错过了状态的改变。
  • Promise的then方法:
  • then方法提供一个供自定义的回调函数,若传入非函数,则会忽略当前then方法。回调函数中会把上一个then中返回的值当做参数值供当前then方法调用。then方法执行完毕后需要返回一个新的值给下一个then调用(没有返回值默认使用undefined)。每个then只可能使用前一个then的返回值。

关于resolve与reject

Promise构造函数接收一个函数作为参数,该函数的两个参数分别是resolve方法和reject方法。如果异步操作成功,则用resolve方法将Promise对象的状态变为"成功"(即从pending变为resolved); 如果异步操作失败,则用reject方法将状态变为"失败"(即从pending变为rejected)。例一:

代码语言:javascript
复制
var getJSON = function(url) {
    var promise = new promise(function (resolve, reject) {
        var client = new XMLHttpRequest();
        client.open('GET', url);
        client.onreadystatechange = handler;
        client.responseType = 'json';
        client.setRequestHeader('Accept', 'application/json');
        client.send();

        function handler() {
            if (this.readyState === this.DONE) {
                if (this.status === 200) {
                    resolve(this.response);
                }
                else {
                    reject(this);
                }
            }
        }
    });

    return promise;
};

getJSON('/posts.json').then(function (json) {
    // continue
}, function (error) {
    // handle errors
});

例二:

代码语言:javascript
复制
getRequest = function (url) {
    var promise = new Promise(function (resolve, reject) {
        var request = require('request');
        request(url, function (error, respones, body) {
            if (error) {
                reject(error);
                return;
            }
            if (respones.statusCode == 200) {
                resolve(body)

            } else {
                reject(respones.status);

            }
        });
    });
    return promise;

};

getRequest("https://github.com/").then(function (result) {
    console.log(result);
}, function (error) {
    console.error('error', error);
});

例三:

代码语言:javascript
复制
updateKinds ({commit, state}) {
      return new Promise(function (resolve, reject) {
        axios.get('/bbg/shop/get_classify', {
          params: {
            sid:  13729792
          } 
        })
        .then(function (response) {
          if (response.data.code == 130) {
            commit(UPDATE_KINDS, response.data.data)
            console.log(response.data.data);
            resolve()
          }
        }).catch(function (error) {
          console.log(error);
        });
      });

返回一个promise,当请求到数据,并且commit之后,我们就额可以resolve()了,这样,就可以在then中执行获取所有内容的方法了。

例四:

代码语言:javascript
复制
var promise = new Promise(function (resolve, reject) {
    console.log('begin do something');
    if (Math.random() * 10.0 > 5) {
        console.log(" run success");
        resolve();
    } else {
        console.log(" run failed");
        reject();

    }
});

这里定义了一个回调方法function(resolve,reject),如果成功了就调用resolve,失败了就会调用reject。

以下例子来源于网上

demo 01

代码语言:javascript
复制
let promise = new Promise(function(resolve, reject) {
  console.log('Promise execute');
  resolve();
});

promise.then(function() {
  console.log('after Resolved');
});

console.log('test async!');

// Promise execute
// test async!
// after Resolved

创建Promise对象表示创建了一个立即执行的代码。

demo 02

代码语言:javascript
复制
new Promise(function(resolve) {
    el.onclick = resolve
}).then(function() {
    console.log('clicked')
})

// 点击el元素多次
// clicked(只会打印一次clicked,因为不会出现两次成功状态)

承诺状态只会改变一次,状态一旦改变就不会再改变。换句话说,回调函数只会执行一次,且成功与失败回调函数只会执行其中一个。

另一个例子:

代码语言:javascript
复制
var p1 = new Promise(function(re, rj) {
    rj()
    re()
})

p1.
then(function() {
    console.log(1)
}, function() {
    console.log(2)
})

// 2(re方法不会执行,因为状态已经变为失败)

demo 03

代码语言:javascript
复制
const preloadImage = function(path) {
    return new Promise(function(resolve, reject) {
        var image = new Image();
        image.onload = resolve;
        image.onerror = reject;
        image.src = path;
    });
};
const a = upload('images/1.jpeg')

// 数秒后在控制台写下Promise的回调函数
a.then(function() {
        console.log('image loaded')
    })
    // image loaded(load事件早已经触发,但是你并没有错过他)

承诺无论你什么时候提供回调函数,只要状态改变过就会执行回调函数。

Promise的then方法(Promise.prototype.then())

按文章开头处的说明,主要需要注意三点:

  • 上一个then中传入了回调函数吗?
  • 上一个then中提供了返回值吗?
  • 若上一个then中若提供了返回值,返回了什么?

首先定义两个function:

代码语言:javascript
复制
let func = function() {
    return new Promise((resolve, reject) => {
        resolve('返回值');
    });
};

let cb = function() {
    return '新的值';
}

然后执行1:

代码语言:javascript
复制
func().then(function () {
    return cb();
}).then(resp => {
    console.warn(resp);
    console.warn('1 =========<');
});

//新的值
//1 =========<

这里resp的值为上面cb()返回的值。

执行2:

代码语言:javascript
复制
func().then(function () {
    cb();
}).then(resp => {
    console.warn(resp);
    console.warn('2 =========<');
});

//undefined
//2 =========<

then中传入的回调方法没有返回值,所以resp为undefined。

执行3:

代码语言:javascript
复制
func().then(cb()).then(resp => {
    console.warn(resp);
    console.warn('3 =========<');
});

//返回值
//3 =========<

then中cb()执行后返回的并不是一个函数,在Promise规范中会自动忽略调当前then,所以会把func(resolve方法)中的返回值供下一个then使用,输出了“返回值”

执行4:

代码语言:javascript
复制
func().then(cb).then(resp => {
    console.warn(resp);
    console.warn('4 =========<');
});

//新的值
//4 =========<

这里把cb当做回调,传入的是cb函数,与执行1的情况相同。

Promise.prototype.catch()

Promise.prototype.catch方法是.then(null, rejection)的别名,用于指定发生错误时的回调函数。

代码语言:javascript
复制
getJSON('/posts.json').then(function(posts) {
  // ...
}).catch(function(error) {
  // 处理 getJSON 和 前一个回调函数运行时发生的错误
  console.log('发生错误!', error);
});

Promise.all()

Promise.all方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。

代码语言:javascript
复制
const p = Promise.all([p1, p2, p3]);

上面代码中,Promise.all方法接受一个数组作为参数,p1、p2、p3都是 Promise 实例,如果不是,就会先调用下面讲到的Promise.resolve方法,将参数转为Promise 实例,再进一步处理。(Promise.all方法的参数可以不是数组,但必须具有 Iterator 接口,且返回的每个成员都是 Promise 实例。)p的状态由p1、p2、p3决定,分成两种情况:

  • 只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
  • 只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。

Promise.race()

Promise.race方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。

代码语言:javascript
复制
const p = Promise.race([p1, p2, p3]);

上面代码中,只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。

Promise.race方法的参数与Promise.all方法一样,如果不是 Promise 实例,就会先调用下面讲到的Promise.resolve方法,将参数转为 Promise 实例,再进一步处理。下面是一个例子,如果指定时间内没有获得结果,就将 Promise 的状态变为reject,否则变为resolve。

代码语言:javascript
复制
const p = Promise.race([
  fetch('/resource-that-may-take-a-while'),
  new Promise(function (resolve, reject) {
    setTimeout(() => reject(new Error('request timeout')), 5000)
  })
]);

p.then(console.log)
.catch(console.error);

上面代码中,如果 5 秒之内fetch方法无法返回结果,变量p的状态就会变为rejected,从而触发catch方法指定的回调函数。

async await

代码语言:javascript
复制
async function testResult() {
    let result = await doubleAfter2seconds(30);
    console.log(result);
}

function doubleAfter2seconds(num) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(2 * num)
        }, 2000);
    } )
}

基本规则:

  • async 表示这是一个async函数,await只能用在这个函数里面。
  • await 表示在这里等待promise返回结果了,再继续执行。
  • await 后面跟着的应该是一个promise对象(当然,如果跟的是其他值也行,只是会立即执行,意义不大)

参考

  • https://segmentfault.com/a/1190000007982668
  • https://segmentfault.com/a/1190000013590295
  • https://segmentfault.com/a/1190000004505028
  • https://segmentfault.com/a/1190000010420744?utm_source=tag-newest
  • https://www.cnblogs.com/zhuzhenwei918/p/6915451.html
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-07-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 开发架构二三事 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 关于resolve与reject
    • demo 01
      • demo 02
        • demo 03
        • Promise的then方法(Promise.prototype.then())
        • Promise.prototype.catch()
        • Promise.all()
        • Promise.race()
        • async await
        • 参考
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档