JS PromiseLike 的判定与使用


一. $.ajax()返回值遇到的问题

当我们执行如下js代码时,可以看到$.ajax()执行后,得到的response对象并不为空,并且response对象的responseJSON属性也确实是有值的。

但是,当我们执行response.responseJSON后,得到的居然是undefined
并且我们使用await 对response对象等待后,得到的就直接是response.responseJSON中的值。

setTimeout(async () => {

    const response = $.ajax({
        url: "https://api.github.com/users/fengyehong123",
        type: 'GET',
    });
    console.log(response);
    console.log(response.responseJSON);  // undefined

    const result = await response;
    console.log(result);

}, 1000);

⏹执行效果如下:

在这里插入图片描述

🤔上述现象是因为 $.ajax()得到的对象是一个 Promise Like对象,Promise Like对象和ES6的new Promise()一样,都是对 Promise A+ 规范的实现,因此可以使用 await 进行等待。


二. Promise A+ 规范

官网: https://promisesaplus.com/

ES6的new Promise()也好,$.ajax()函数返回的Promise Like对象也好,
都只是Promise A+规范的一种实现,该规范告诉我们如何自己实现一个Promise。


三. 判断是否为PromiseLike

⏹如果一个值的类型为 object 或者 function
并且 该值还存在一个then方法
那么 该值就是一个 PromiseLike 对象。

// 判断是否为 Promise Like
 function isPromiseLike(value) {

    if(value === null) {
        return false;
    }
    
    if ((typeof value === 'object' || typeof value === 'function') && (typeof value.then === 'function')){
        return true;
    }

    return false;
}

3.1 判断ES6的new Promise()

⏹ES6 的 new Promise() 是 Promise A+ 规范的实现,所以肯定是一个 PromiseLike 对象

const promise_obj = new Promise((resolve, reject) => {
    resolve('枫叶红');
});
console.log(isPromiseLike(promise_obj) ? "promise_obj是PromiseLike对象" : "promise_obj非PromiseLike对象");

3.2 判断包含then方法的对象

⏹定义一个对象,对象里面有一个then方法,方法里面是耗时操作。符合该对象是一个Promise Like对象。

const then_response = {
    then: function(resolve, reject) {
        setTimeout(() => {
            resolve('贾飞天');
        }, 1000)
    }
}
console.log(
	isPromiseLike(then_response) 
	? "then_response是PromiseLike对象" : "then_response非PromiseLike对象"
);
// then_response是PromiseLike对象

(async (response) => {
    /*
        此处的response实际上是then_response
        因为 then_response 是一个 Promise Like 对象
        要想await的话,必须包裹在 函数中
        因此此处定义了一个立即执行函数,还可以避免给函数取名的麻烦
    */
    const result = await response;
    console.log(result);
})(then_response);

3.3 判断$.ajax()返回的对象

// ⏹两秒之后发送ajax请求
setTimeout(async () => {

    const response = $.ajax({
        url: "https://api.github.com/users/fengyehong123",
        type: 'GET',
    });
    
    // 是一个PromiseLike对象
    console.log(
		isPromiseLike(response) ? "response是PromiseLike对象" : "response非PromiseLike对象"
	);
    // response是PromiseLike对象

    // 正因为是 PromiseLike对象 ,所以才可以进行await
    const result = await response;
    console.log(result);
}, 2000);

⏹也就是说,我们之后的$.ajax()函数可以这么写

// ajax的请求对象
const jqRequest = $.ajax({
    url,
    method: 'GET'
});

// doneCallBack,failCallBack,alwaysCallback 是从外部传入的回调函数
jqRequest.done(function(data, textStatus, jqXHR) {
    doneCallBack && doneCallBack(data);
}).fail(function(jqXHR, textStatus, errorThrown) {
    failCallBack && failCallBack();
}).always(function() {
    alwaysCallback && alwaysCallback();
});

⏹也可以这么写,从而可以避免回调的方式

document.querySelector('#btn').addEventListener('click', async function() {

    const url = "https://api.github.com/users/fengyehong123";
    // 后端的返回值
    let result = null;

    try {
        result = await $.ajax({
            url,
            type: 'GET',
        });
    } catch (error) {

        const {responseJSON} = error;
        console.log(`请求失败!原因是: ${responseJSON}`);
    } finally {
        console.log("请求完成!");
    }

    if(!result) {
    	// 进行相应的业务处理
        return;
    }
   
    console.log("返回的最终值为:");
    console.log(result);
});
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值