Promise入门_2
3. Promise 的几个关键问题
1. 如何改变 promise 的状态?
(1)resolve(value):如果当前是 pending
就会变为 resolved
(2)reject(reason):如果当前是 pending
就会变为 rejected
(3)抛出异常:如果当前是 pending
就会变为 rejected
const p = new Promise((resolve, reject) => {
//resolve(1) // promise变为resolved成功状态
//reject(2) // promise变为rejected失败状态
throw new Error('出错了') // 抛出异常,promise变为rejected失败状态,reason为抛出的error
})
p.then(
value => {},
reason => {console.log('reason',reason)}
)
// reason Error:出错了
2. 一个 promise 指定多个成功/失败回调函数(调用多次then方法),都会调用吗?
如果promise里面用reject函数改变了promise实例的状态,那就要在外面的then函数里给它绑定一个失败的回调函数,不然会报错。
当 promise
改变为对应状态时都会调用。
const p = new Promise((resolve, reject) => {
//resolve(1)
reject(2)
})
p.then(
value => {},
reason => {console.log('reason',reason)}
)
p.then(
value => {},
reason => {console.log('reason2',reason)}
)
// reason 2
// reason2 2
3. 改变 promise 状态和指定回调函数谁先谁后?(意思是promise的代码在运行时,resolve改变状态(调用)的代码先执行还是then方法绑定回调函数先执行)
如:
都有可能,常规是先绑定回调再改变状态,但也可以先改状态再绑定回调。这涉及到事件轮询。
指定回调和调用回调是两个概念,指定回调并没有调用,指定回调也属于初始化代码。调用回调是属于回调代码。绑定回调代码不等于执行回调。
执行器函数是同步执行的,一般来说会先改变状态。如果resolve调用写在定时器里,则then先执行绑定函数,因为这时候里面的resolve调用会变成异步操作了,有事件轮询里的事件模块调用。
promise是微任务先执行,setTimeou里面是回调函数,js走到这里会将其给到定时器管理模块,触发后放入宏任务轮询,这个时候主线程不会等resolve,会执行初始化代码then方法,但是处理结果的回调(then方法里面的匿名函数)会等状态改变后才被调用。
then是异步微任务,所以then方法里面的参数也(两个匿名函数)属于回调代码,会等初始化代码执行完毕后等它们的Promise实例的状态改变时才会被调用。注意:new Promise里面的回调函数是初始化代码,但是如果里面套定时器,那么定时器里的回调函数就是回调代码,尽管在定时器的回调里调用改变promise状态的方法也是一样,这时候主线程不会等。如:
1,
2
- 如何先改状态再指定回调?
(1)在执行器中直接调用 resolve()/reject()
(2)延迟更长时间才调用 then()
let p = new Promise((resolve, reject) => {
// setTimeout(() => {
resolve('OK');
// }, 1000); // 有异步就先指定回调,否则先改变状态
});
p.then(value => {
console.log(value);
},reason=>{
})
- 什么时候才能得到数据?(意思是回调函数什么时候执行)
(1)如果先指定的回调,那当状态发生改变时,回调函数就会调用得到数据
(2)如果先改变的状态,那当指定回调时,回调函数就会调用得到数据
new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1) // 改变状态
}, 1000)
}).then( // 指定回调函数 (先指定)
value => {},
reason =>{}
)
此时,先指定回调函数,保存当前指定的回调函数;后改变状态(同时指定数据),然后异步执行之前保存的回调函数。
new Promise((resolve, reject) => {
resolve(1) // 改变状态
}).then( // 指定回调函数
value => {},
reason =>{}
)
这种写法,先改变的状态(同时指定数据),后指定回调函数(不需要再保存),直接异步执行回调函数。
4. promise.then() 返回的新 promise 的结果状态由什么决定?
then方法总会返回一个新的Promise的实例:
(1)简单表达:由 then()
指定的回调函数执行的结果决定
let p = new Promise((resolve, reject) => {
resolve('ok');
});
//执行 then 方法
let result = p.then(value => {
console.log(value);
}, reason => {
console.warn(reason);
});
console.log(result);
(2)详细表达:
① 如果抛出异常,新 promise
变为 rejected
,reason
为抛出的异常
let p = new Promise((resolve, reject) => {
resolve('ok');
});
//执行 then 方法
let result = p.then(value => {
//1. 抛出错误
throw '出了问题';
}, reason => {
console.warn(reason);
});
console.log(result);
② 如果返回的是非 promise 的任意值,新 promise 变为 resolved,value 为返回的值
let p = new Promise((resolve, reject) => {
resolve('ok');
});
//执行 then 方法
let result = p.then(value => {
//2. 返回结果是非 Promise 类型的对象
return 521;
}, reason => {
console.warn(reason);
});
console.log(result);
③ 如果返回的是另一个新 promise
,此 promise
的结果就会成为新 promise
的结果
let p = new Promise((resolve, reject) => {
resolve('ok');
});
//执行 then 方法
let result = p.then(value => {
//3. 返回结果是 Promise 对象
return new Promise((resolve, reject) => {
// resolve('success');
reject('error');
});
}, reason => {
console.warn(reason);
});
console.log(result);
new Promise((resolve, reject) => {
resolve(1)
}).then(
value => {
console.log('onResolved1()', value)
},
reason => {
console.log('onRejected1()', reason)
}
).then(
value => {
console.log('onResolved2()', value)
},
reason => {
console.log('onRejected2()', reason)
}
)
//结果:
// onResolved1() 1
// onResolved2() undefined
5.promise 如何串联多个操作任务?
(1)promise 的 then() 返回一个新的 promise,可以并成 then() 的链式调用
(2)通过 then 的链式调用串联多个同步/异步任务
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('OK');
}, 1000);
});
p.then(value => {
return new Promise((resolve, reject) => {
resolve("success");
});
}).then(value => {
console.log(value); // success
}).then(value => {
console.log(value); // undefined
})
let p=new Promise((resolve,reject)=>{
setTimeout(() => {
resolve("success");
}, 2000);
});
let rp=p.then(value=>{
console.log(value);//结果:success
//.then的确返回promise对象,但这个对象的值由回调返回的值决定,
//这里没有声明返回值,所以返回undefined,
//那么下一个then获取到的值就是undefined。
},reason=>{
console.log(reason);
});
let rp2=rp.then(value=>{
console.log("成功1");
console.log(value);//结果:undefind
},reason=>{
console.log("失败1");
});
let rp3=rp2.then(value=>{
console.log("成功2");
console.log(value);//结果:undefind
},reason=>{
console.log("失败2");
});
6.Promise 异常穿透(传透)?
(1)当使用 promise 的 then 链式调用时,可以在最后指定失败的回调
(2)前面任何操作出了异常,都会传到最后失败的回调中处理
new Promise((resolve, reject) => {
//resolve(1)
reject(1)
}).then(
value => {
console.log('onResolved1()', value)
return 2
}
).then(
value => {
console.log('onResolved2()', value)
return 3
}
).then(
value => {
console.log('onResolved3()', value)
}
).catch(
reason => {
console.log('onRejected1()', reason)
}
)
// onRejected1() 1
相当于这种写法:多写了很多reason => {throw reason}
new Promise((resolve, reject) => {
//resolve(1)
reject(1)
}).then(
value => {
console.log('onResolved1()', value)
return 2
},
reason => {throw reason} // 抛出失败的结果reason
).then(
value => {
console.log('onResolved2()', value)
return 3
},
reason => {throw reason} // 抛出失败的结果reason
).then(
value => {
console.log('onResolved3()', value)
},
reason => {throw reason} // 抛出失败的结果reason
).catch(
reason => {
console.log('onRejected1()', reason)
}
)
// onRejected1() 1
所以失败的结果是一层一层处理下来的,最后传递到 catch 中。
或者,将 reason => {throw reason}
替换为 reason => Promise.reject(reason)
也是一样的。
7.中断 promise 链
当使用 promise
的 then
链式调用时,在中间中断,不再调用后面的回调函数
办法:在回调函数中返回一个 pending
状态的 promise
对象
new Promise((resolve, reject) => {
//resolve(1)
reject(1)
}).then(
value => {
console.log('onResolved1()', value)
return 2
}
).then(
value => {
console.log('onResolved2()', value)
return 3
}
).then(
value => {
console.log('onResolved3()', value)
}
).catch(
reason => {
console.log('onRejected1()', reason)
}
).then(
value => {
console.log('onResolved4()', value)
},
reason => {
console.log('onRejected2()', reason)
}
)
// onRejected1() 1
// onResolved4() undefined
为了在 catch
中就中断执行,可以这样写:
new Promise((resolve, reject) => {
//resolve(1)
reject(1)
}).then(
value => {
console.log('onResolved1()', value)
return 2
}
).then(
value => {
console.log('onResolved2()', value)
return 3
}
).then(
value => {
console.log('onResolved3()', value)
}
).catch(
reason => {
console.log('onRejected1()', reason)
return new Promise(() => {}) // 返回一个pending的promise
}
).then(
value => {
console.log('onResolved4()', value)
},
reason => {
console.log('onRejected2()', reason)
}
)
// onRejected1() 1
在 catch
中返回一个新的 promise
,且这个 promise
没有结果。
由于,返回的新的 promise
结果决定了后面 then
中的结果,所以后面的 then
中也没有结果。
这就实现了中断 promise
链的效果。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构