Promise 对象特点

对象的状态不受外界影响。 Promise对象代表一个异步操作, 有三种状态: pending( 进行中)、 fulfilled( 已成功)
和rejected( 已失败)。 只有异步操作的结果, 可以决定当前是哪一种状态, 任何其他操作都无法改变这个状态。

一旦状态改变, 就不会再变, 任何时候都可以得到这个结果。 Promise对象的状态改变, 只有两种可能:
从pending变为fulfilled和从pending变为rejected。 只要这两种情况发生, 状态就凝固了, 不会再变了, 会一直保持这个结果,
这时就称为 resolved( 已定型)。 如果改变已经发生了, 你再对Promise对象添加回调函数, 也会立即得到这个结果。

Promise缺点

无法取消promise, 一旦新建它会立即执行, 无法中途取消.

如果不设置回调函数, promise内部抛出的错误, 不会反应到外部.

当处于pending 状态时, 无法得知目前进展到那一阶段.

静态方法

Promise.reslove()

将现有对象转换为Promise对象

如果参数是promise实例,则直接返回这个实例

如果参数是thenabled对象(有then方法的对象),则先将其转换为promise对象,然后立即执行这个对象的then方法

如果参数是个原始值,则返回一个promise对象,状态为resolved,这个原始值会传递给回调

没有参数,直接返回一个resolved的Promise对象

Promise.reject()

同上,不同的是返回的promise对象的状态为rejected

Promise.all()

接收一个Promise实例的数组或具有Iterator接口的对象

如果元素不是Promise对象,则使用Promise.resolve转成Promise对象

如果全部成功,状态变为resolved,返回值将组成一个数组传给回调

只要有一个失败,状态就变为rejected,返回值将直接传递给回调

all() 的返回值也是新的Promise对象

Promise.race()

只要有一个Promise实例率先发生变化(无论是状态变成resolved还是rejected)都触发then中的回调,返回值将传递给回调

race()的返回值也是新的Promise对象

代码用法和误区

常见用法

promise 的神奇之处在于让我们能够在回调函数里面使用 return 和 throw

如果没有任何返回,将默认返回 undefinedloadAsync1()

.then(function(data1){

return loadAsync2(data1)

})

.then(function(data2){

return loadAsync3(data2)

})

.then(okFn, failFn)

************************************

loadAsync1()

.then(function(data1){

loadAsync2(data1)

})

.then(function(data2){

loadAsync3(data2)

})

.then(res=>console.log(res))

复制代码

catch()与then(null, fn)

不等同情况,此时catch捕获并不是ajaxLoad1错误 而是ajaxLoad2的错误。**看场景有时要结合起来使用**

```js

ajaxLoad1()

.then(res=>{ return ajaxLoad2() })

.catch(err=> console.log(err))

----------------------

// 结合使用

ajaxLoad1()

.then(res=>{ return ajaxLoad2() }, err=>console.log(err))

.catch(err=> console.log(err))

```

复制代码

穿透 Fall Through

如果then或catch接收的不是函数,那么就会发生穿透行为,所以在应用过程中,应该保证then接收到的参数始终是一个函数

new Promise(resolve=>resolve(8))

.then(1)

.catch(null)

.then(Promise.resolve(9))

.then(res=> console.log(res))

// 8

复制代码

用Promise实现一个Ajax操作

// 0 未初始化未调用open

// 1.启动 调用open 未调用 send

// 2. 发送 已调用send() 但是未响应

// 3. 接收 已经接收部分响应数据

// 4.完成 完成全部数据响应

const ajax = function (params){

if (!params.url) return

const promise = new Promise((resolve, reject) => {

const handler = function (){

if (this.readyState !== 4) return

if (this.status == 200) {

try {

let resonse = JSON.parse(this.responseText)

resolve(resonse)

} catch (error) {

reject(error)

}

} else {

reject(new Error(this.statusText))

}

}

const xhr = new XMLHttpRequest()

if (params.method.toLowerCase() == 'get') {

xhr.open('get', url + '?' + formatParams(params.data));

xhr.send()

} else {

xhr.open('post', url);

xhr.send(JSON.stringify(params.data));

}

xhr.onreadystatechange = handler

xhr.responseType = 'json'

xhr.setRequestHeader('Accept', 'application/json');

})

return promise

function formatParams(obj){

if (!data) return

var arr = []

for (let i in obj) {

arr.push(`${encodeURIComponent(i)}=${encodeURIComponent(obj[i])}`)

}

return arr.join('&')

}

}

复制代码

Promise常见问题

reject 和 catch 的区别

- promise.then(onFulfilled, onRejected)

在onFulfilled中发生异常的话,在onRejected中是捕获不到这个异常的。

- promise.then(onFulfilled).catch(onRejected)

.then中产生的异常能在.catch中捕获

复制代码

如果在then中抛错,而没有对错误进行处理(即catch),那么会一直保持reject状态,直到catch了错误

```JS

/* 例4.1 */

function taskA() {

console.log(x);

console.log("Task A");

}

function taskB() {

console.log("Task B");

}

function onRejected(error) {

console.log("Catch Error: A or B", error);

}

function finalTask() {

console.log("Final Task");

}

var promise = Promise.resolve();

promise

.then(taskA) // 抛出错误,不继续Task A”

.then(taskB) // .then没有捕获A抛出的错,不打印 “Task B”

.catch(onRejected) // 捕获了A的错,打印错误信息

.then(finalTask); // 错误已经被捕获,执行resolve

-------output-------

Catch Error: A or B,ReferenceError: x is not defined

Final Task

```

复制代码

每次调用then都会返回一个新创建的promise对象,而then内部只是返回的数据

```JS

//方法1:对同一个promise对象同时调用 then 方法

var p1 = new Promise(function (resolve) {

resolve(100);

});

p1.then(function (value) {

return value * 2;

});

p1.then(function (value) {

return value * 2;

});

p1.then(function (value) {

console.log("finally: " + value);

});

-------output-------

finally: 100

------------------------------------------------------

//方法2:对 then 进行 promise chain 方式进行调用

var p2 = new Promise(function (resolve) {

resolve(100);

});

p2.then(function (value) {

return value * 2;

}).then(function (value) {

return value * 2;

}).then(function (value) {

console.log("finally: " + value);

});

-------output-------

finally: 400

```

复制代码

在异步回调中抛错,不会被catch到

```JS

// Errors thrown inside asynchronous functions will act like uncaught errors

var promise = new Promise(function(resolve, reject) {

setTimeout(function() {

throw 'Uncaught Exception!';

}, 1000);

});

promise.catch(function(e) {

console.log(e); //This is never called

});

```复制代码

技术
下载桌面版
GitHub
Gitee
SourceForge
百度网盘(提取码:draw)
云服务器优惠
华为云优惠券
腾讯云优惠券
阿里云优惠券
Vultr优惠券
站点信息
问题反馈
邮箱:[email protected]
吐槽一下
QQ群:766591547
关注微信