Promise简介

相当于一个容器,允许你为异步操作的成功和失败分别绑定相应的处理方法,保存着未来才会结束的事件(异步操作)的一个结果

各种异步操作都可以用同样的方法进行处理

对象的状态不受外界影响,处理异步操作有三个状态:

  • pending(进行)
  • fulfilled(成功)
  • rejected(失败)

一旦状态改变,就不会再变化,任何时候都可以得到这个结果

基本使用

function timeout(ms) {
    // Promise 对象
    return new Promise((resolved, rejected) => {
        let res = {
            code: 200,
            data: {
                msg: 'Hello Promise resolved'
            }
        }
        setTimeout(() => {
            if (res.code === 200) {
                resolved(res.data)
            } else {
                rejected("Promise reject")
            }
        }, ms)
    })
}
// res 接收成功回调的结果, err 结束失败回调的结果
timeout(2000).then(res => {
    console.log(res)
}, err => {
    console.log(err)
})

then

第一个参数是resolve回调函数,第二个参数可选,为reject状态的回调函数

then()方法返回一个新的promise实例,所以可以采用链式编程的写法

timeout(1000).then(res => {
    console.log(res);  // { msg: 'Hello Promise resolved' }
    return res.msg; 
}).then(res => {
    console.log(res);	// Hello Promise resolved
})

catch

接收reject状态的回调函数

timeout(1000).then(res => {
    console.log(res)
}).catch(err => {
    console.log(err);
})
// --------------- 等价于 ----------------
timeout(1000).then(res => {
    console.log(res)
}).then(null, err => {
    console.log(err);
})

Promise封装ajax

const XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
const getJSON = function (url) {
    return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        xhr.open('GET', url);
        xhr.responseType = 'json';
        xhr.onreadystatechange = handler;
        xhr.setRequestHeader('ACCEPT', 'appliction/json');
        // 发送
        xhr.send();

        function handler() {
            console.log(this);
            if (this.readyState === 4) {
                if (this.status === 200) {
                    resolve(this.location);
                } else {
                    reject(new Error(this.statusText));
                }
            }
        }
    })
}

getJSON("https://geoapi.heweather.net/v2/city/lookup?location=beij&key=xxx").then(res => {
    console.log(res);
}).catch(err => {
    console.log(err);
})

Promise方法

resole

能将现有的任何对象转换成一个Promise对象

let p = Promise.resolve('foo');
// 等价于 ==> 
let p1 = new Promise(resolve => resolve('foo'));

p.then(data => {
    console.log(data); // foo
})

reject

返回一个带有拒绝原因的Promise对象。

let p = Promise.reject(new Error('fail'));
p.then(res => {
    
}).catch(err=> {
    console.log(err); // Error: fail
})

all

返回一个 Promise实例,此实例在 iterable 参数内所有的 promise 都完成(resolved)或参数中不包含 promise 时回调完成(resolve);如果参数中 promise 有一个失败(rejected),此实例回调失败(reject),失败的原因是第一个失败 promise 的结果。

const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3]).then((values) => {
  console.log(values);
});

allSelected

返回一个在所有给定的promise都已经fulfilledrejected后的promise,并带有一个对象数组,每个对象表示对应的promise结果。

const promise1 = Promise.resolve(3);
const promise2 = new Promise((resolve, reject) => setTimeout(reject, 100, 'foo'));
const promises = [promise1, promise2];

Promise.allSettled(promises).then(results => results.forEach(result => console.log(result.status)));
// expected output:
// "fulfilled"
// "rejected"

race

返回一个 promise,一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝。

const timeout = function (ms) {
    return new Promise((resolved, rejected) => {
        setTimeout(() => {
            rejected(new Error('请求超时!'))
        }, ms)
    })
}
const requestFile = function() {
    return new Promise((resolved, rejected) => {
        // 请求文件
    })
}
// 如果3秒内requestFile没有相应,将返回请求超时
let p = new Promise.race([requestFile(),timeout(3000)]);
p.then(res=> {
    // ... 
})

finally

返回一个Promise,在promise结束时,无论结果是fulfilled或者是rejected,都会执行指定的回调函数。这为在Promise是否成功完成后都需要执行的代码提供了一种方式。

timeout(1000).then(res => {
    console.log(res)
}).catch(err => {
    console.log(err);
}).finally(() => {
    console.log('finally')
})

async

async返回一个Promise对象

async是Generator的一个语法糖

使异步操作更加方便

await 操作符用于等待一个Promise对象,返回 Promise 对象的处理结果。它只能在异步函数 async function中使用。如果等待值不是promise对象,await 会把等待值转换为已正常处理的Promise,然后等待其处理结果。

async function fun() {
    return await 'hello async';
}
fun().then(v => {console.log(v)}).catch(e=>console.log(e));

如果async函数中有多个await,then会等待所有的await指令运行完的结果,才去执行

async function fun() {
    let s = await 'hello async';
    let data = await s.split('');
    return data;
}
fun().then(v => {console.log(v)}).catch(e=>console.log(e));

如果一个await 的结果为reject,则立即返回reject的结果,不会执行后去的await

async function f() {
   await Promise.reject('出错');
   return await Promise.resolve('完成');
}
f().then(v => {console.log(v)}).catch(e=>console.log(e));	// 出错

使用try...catch使得某个await结果为reject时继续执行

async function f() {
    try {
        await Promise.reject('出错');
    } catch (err) {
        console.log(err); 	// 出错
    }
   return await Promise.resolve('完成');
}
f().then(v => {console.log(v)}).catch(e=>console.log(e));	// 完成

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!

Vue组件与组件通信 上一篇
ES6中数组的扩展方法 下一篇