【大白话】说Promise是什么,有什么,怎么用

169 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第7天,点击查看活动详情

写在前面

以下所述内容大部分为本人在MDN-Promise,ES6标准入门(第二版)192页开始,和一些博客介绍的消化咀嚼产出,带着粗浅的认识和个人主观偏向,可能理解的不是很到位,想看具体讲解的点下面传送门

Promise是什么

按照官方的话来说,Promise是异步编程的一种解决方案,里面通常保存着异步操作事件的结果。以前用嵌套的回调函数解决异步(产生回调地狱),现在用Promise。 所以promise是用来

  • 解决异步的问题
  • 可以并发多个请求,获取并发请求中的数据

Promise有什么

  1. 有三种状态:Pending(进行中)、Resolved(成功,又称Fulfilled)和Rejected(失败),只有两种变化情况,由Pending变为Resolved或Rejected。这些状态只由操作的结果决定,状态一旦发生了改变,就会一直保持,后续回调无法改变。
  2. 有各种内置方法:reject,resolve,then,catch,all,race。

Promise怎么用

基本使用:

var promise = new Promise(function(resolve, reject) {
	if ( /* 异步操作成功 */ ) {
		resolve(value);
	} else {
		reject(error);
	}
});

Promise构造函数接收一个函数作为参数,该函数的两个参数分别是resolve和reject。resolve为成功状态,并返回操作结果,reject为失败,且返回错误报告。

Promise实例生成后,可以用then方法(在Promise原型对象内置有),接收两个参数,分别指定Resolved状态和Reject状态的回调函数。成功value,失败为reason或error。

promise.then(function(value) {
// success
}, function(error) {
// failure
});

完整示例:

function doDelay(time){
    return new Promise((resolve,reject) => {
        setTimeout(() => {
            if(){
                resolve("xxx")
               }
            else{
                reject("xxx")
             }
        }),time
    })
}

doDelay(200).then(value => {
    
},reason => {
    
})

简直不要太简单,下面简单说下Promise其他方法

  • Promise.prorotype.catch() 方法:失败的回调函数,用来指定reject的回调,即使上面resolve报错了,也能执行到catch。 说明:是then的语法糖,相当于:then(undefined,onRejected)
  • Promise.all 方法:接收一个包含n个promise的数组 说明:返回一个新的promise,只有所有的promise都成功才成功,只要有一个失败则直接失败且第一个失败的实例作为返回值,一般用在一次加载很多请求,全加载成功在渲染。
  • Promise.race 方法:跟 all 一样,接收一个包含n个promise的数组,只要有一个实例改变状态,该实例就作为返回值返回 说明:返回一个新的promise,第一个完成的promise的结果状态就是最终的结果状态
  • Promise.allSettled():all的改进版,跟all一样,但是等入参的promise状态都发生了变更才返回,返回一个包含他们状态的Promise。
  • finally():不接收参数,不管Promimse对象最后状态是什么,都会执行的操作。
myPromise()
.then(
    function(value){
        console.log('resolved');
    }, 
    function(err, data){
        console.log('rejected');
    }
);

//或者
myPromise()
.then(function(data){
    console.log('resolved');
})
.catch(function(reason){
    console.log('rejected');
});

myPromise()
.all([runAsync1(), runAsync2(), runAsync3()])
.then(function(results){
    console.log(results);
});

为什么要用Promise

  1. 指定回调函数方式更加灵活
  2. 支持链式调用,不阻塞Promise相关的任何程序,且保持异步关系来解决回调地狱问题

Promise在ajax中的应用(封装)

发送ajax请求的四个步骤

// 1.创建 XMLHttpRequest 对象
var xhr = new XMLHttpRequest();
// 2.设置状态监听函数
xhr.onreadystatechange = function () {// 状态发生变化时,触发回调函数
    if (xhr.readyState !== 4) return;
    if (xhr.status === 200) {
        // 成功:从服务器获取数据,通过responseText拿到响应的文本
        console.log(xhr.responseText)
    } else {
        // 失败,根据响应码判断失败原因
        new Error(xhr.statusText)
    }
};
// 3.规定请求的类型、URL 以及是否异步处理请求
xhr.open("GET", url, true);
// 4.将请求发送到服务器
xhr.send();

开发中一般使用promise对ajax进行一个异步封装,具体如下:

// Promise封装Ajax请求
function ajax(method, url, data) {
    var xhr = new XMLHttpRequest();
    return new Promise(function (resolve, reject) {
        xhr.onreadystatechange = function () {
            if (xhr.readyState !== 4) return;
            if (xhr.status === 200) {
                resolve(xhr.responseText);
            } else {
                reject(xhr.statusText);
            }

        };
        xhr.open(method, url);
        xhr.send(data);
    });
}

ajax('GET', '/api/xxx').then(function (data) {
    // 成功,拿到响应数据
    console.log(data);
}).catch(function (status) {
    // 失败,根据响应码判断失败原因
    new Error(status)
});

对该技术有更深的认识后,在更...