Promise面试题

Promise的介绍和优点

es6中的promise时异步编程的一种方案. 从语法上来讲, promise是一个对象, 它可以获取异步操作的消息

promise对象, 可以将异步操作以同步的流程表达出来

好处:

可以很好的解决回调地狱问题 (避免了层层嵌套的回调函数)

语法非常简洁. promise对象提供简介的api, 使得控制异步操作更加容易

Promise的基本用法

1 new实例化一个promise对象, promise的构造函数中传递一个参数, 是一个函数, 该函数用于处理异步任务

2 传入两个参数: resolve和reject, 分别代表异步执行成功后的回调函数和失败后的回调函数

3 通过promise.then()处理返回结构

实例

// 第一步:model层的接口封装
const promise = new Promise((resolve, reject) => {
    // 这里做异步任务(比如ajax 请求接口。这里暂时用定时器代替)
    setTimeout(function() {
        var data = { retCode: 0, msg: 'qianguyihao' }; // 接口返回的数据
        if (data.retCode == 0) {
            // 接口请求成功时调用
            resolve(data);
        } else {
            // 接口请求失败时调用
            reject({ retCode: -1, msg: 'network error' });
        }
    }, 100);
});

// 第二步:业务层的接口调用。这里的 data 就是 从 resolve 和 reject 传过来的,也就是从接口拿到的数据
promise.then(data => {
    // 从 resolve 获取正常结果
    console.log(data);
}).catch(data => {
    // 从 reject 获取异常结果
    console.log(data);
});

Promise对象的3个状态

初始化状态(等待状态): pending

成功状态: fullfilled

失败状态: rejected

(1)当new Promise()执行之后,promise对象的状态会被初始化为pending,这个状态是初始化状态。new Promise()这行代码,括号里的内容是同步执行的。括号里定义一个function,function有两个参数:resolve和reject。如下:

  • 如果请求成功了,则执行resolve(),此时,promise的状态会被自动修改为fullfilled。
  • 如果请求失败了,则执行reject(),此时,promise的状态会被自动修改为rejected

(2)promise.then()方法,括号里面有两个参数,分别代表两个函数 function1 和 function2:

  • 如果promise的状态为fullfilled(意思是:如果请求成功),则执行function1里的内容
  • 如果promise的状态为rejected(意思是,如果请求失败),则执行function2里的内容

Promise处理多次ajax请求(链式调用)

promise可以把原本的多层嵌套调用改为链式调用

/*
	基于Promise发送Ajax请求
*/
function queryData(url) {
    var promise = new Promise((resolve, reject) => {
        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function() {
            if (xhr.readyState != 4) return;
            if (xhr.readyState == 4 && xhr.status == 200) {
                // 处理正常情况
                resolve(xhr.responseText); // xhr.responseText 是从接口拿到的数据
            } else {
                // 处理异常情况
                reject('接口请求失败');
            }
        };
        xhr.responseType = 'json'; // 设置返回的数据类型
        xhr.open('get', url);
        xhr.send(null); // 请求接口
    });
    return promise;
}
// 发送多个ajax请求并且保证顺序
queryData('http://localhost:3000/api1')
    .then(
        data1 => {
            console.log(JSON.stringify(data1));
            // 请求完接口1后,继续请求接口2
            return queryData('http://localhost:3000/api2');
        },
        error1 => {
        	console.log(error1);
        }
    )
    .then(
        data2 => {
            console.log(JSON.stringify(data2));
            // 请求完接口2后,继续请求接口3
            return queryData('http://localhost:3000/api3');
        },
        error2 => {
        	console.log(error2);
        }
    )
    .then(
        data3 => {
            // 获取接口3返回的数据
            console.log(JSON.stringify(data3));
        },
        error3 => {
        	console.log(error3);
        }
	);

Promise的常用API: 实例方法

promise.then(): 获取异步任务的正常结果

promise.catch(): 获取异步任务的异步结果

promise.finaly(): 异步任务无论成功与否, 都会执行

queryData()
    .then(data => {
        // 从 resolve 获取正常结果
        console.log('接口请求成功时,走这里');
        console.log(data);
    })
    .catch(data => {
        // 从 reject 获取异常结果
        console.log('接口请求失败时,走这里');
        console.log(data);
    })
    .finally(() => {
    	console.log('无论接口请求成功与否,都会走这里');
    });
queryData()
    .then(
        data => {
            // 从 resolve 获取正常结果
            console.log('接口请求成功时,走这里');
            console.log(data);
        },
        data => {
            // 从 reject 获取异常结果
            console.log('接口请求失败时,走这里');
            console.log(data);
        }
    )
    .finally(() => {
    	console.log('无论接口请求成功与否,都会走这里');
});

Promise的常用API: 对象方法

promise.all(): 并发处理多个异步任务, 所有任务都执行成功, 才能得到结果.

promise.race(): 并发处理多个异步处理, 只要一个任务执行成功, 就能得到结果

/*
封装 Promise 接口调用
*/
function queryData(url) {
    return new Promise((resolve, reject) => {
        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function() {
            if (xhr.readyState != 4) return;
            if (xhr.readyState == 4 && xhr.status == 200) {
                // 处理正常结果
                resolve(xhr.responseText);
            } else {
                // 处理异常结果
                reject('服务器错误');
            }
        };
        xhr.open('get', url);
        xhr.send(null);
    });
}

var promise1 = queryData('http://localhost:3000/a1');
var promise2 = queryData('http://localhost:3000/a2');
var promise3 = queryData('http://localhost:3000/a3');

Promise.all([promise1, promise2, promise3]).then(result => {
	console.log(result);
});
/*
封装 Promise 接口调用
*/
function queryData(url) {
    return new Promise((resolve, reject) => {
        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function() {
            if (xhr.readyState != 4) return;
            if (xhr.readyState == 4 && xhr.status == 200) {
                // 处理正常结果
                resolve(xhr.responseText);
            } else {
                // 处理异常结果
                reject('服务器错误');
            }
        };
        xhr.open('get', url);
        xhr.send(null);
    });
}

var promise1 = queryData('http://localhost:3000/a1');
var promise2 = queryData('http://localhost:3000/a2');
var promise3 = queryData('http://localhost:3000/a3');

Promise.race([promise1, promise2, promise3]).then(result => {
	console.log(result);
});
原文地址:https://www.cnblogs.com/bnzw/p/14207838.html