从如何使用到如何实现一个Promise
promise是什么?主要用来解决什么问题?
Promise是异步编程的一种解决方案,比传统解决方案--回调函数和事件--更合理更强大。
Promise
特点:
(1)对象的状态不受外界影响。Promise
对象代表一个异步操作,有三种状态:pending
(进行中),fulfilled
(已成功)和reject
(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其它操作都无法改变这个状态。这也是Promise
(承诺)这个名字的由来。
(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise
对象的状态改变,只有两种可能:从pending
变为fulfilled
和从pending
变为rejected
。
promise主要用来解决:
-
回调地狱
-
并发请求
-
异步方案优化(但它本身不是异步的,new Promise()后,它会立即执行)
promise基本用法
ES6规定,Promise
对象是一个构造函数,用来生成Promise
实例
下面代码创造了一个Promise
实例
const?promise?=?new?Promise(function(resolve,reject){
????//...
????if(/*异步操作成功*/){
???????resolve(value)
????}else{
????????//异步操作失败
????????reject(error)
????}
})
Promise
构造函数接受一个函数作为参数,该函数的两个参数分别是resolve
和reject
.他们是两个函数,由JavaScript引擎提供,不用自己部署。
resolve
函数的作用是,将Promise
对象的状态从“未完成”变成“成功”(即从pending变为resolve),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject
函数的作用是,将Promise
对象的状态从“未完成”变成“失败”(即从pending变为rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
Promise
实例生成以后,可以用then
方法分别指定resolved
状态和rejected
状态的回调函数,或用catch
方法指定rejected
状态的回调函数。
promise.then(res=>{
????//success
},error=>{
????//error
}).catch(err=>{})
then
方法可以接受两个回调函数作为参数,第一个回调函数是Promise
对象的状态变为resolved
时调用,第二个回调函数是Promise
对象的状态变为rejected
时调用。其中,第二个函数是可选的,不一定要提供。这两个函数都接收Promise
对象传出的值作为参数。
「Ok,通过上面对promise基本用法的描述,我们大概知道了一个promise类里面都应该包含哪些内容了:」
-
promise状态:pending,fulfilled,rejected
-
promise返回值
-
执行器:promise执行入口(也就是你传入的那个函数)
-
resolve:改变promise状态为fulfilled
-
reject:改变promise状态为rejected
-
then:接收两个回调,onFulfilled, onRejected。分别在promise状态变为fulfiled或rejected后执行
-
catch:接受一个回调,在promise状态变为rejected后执行
简单实现一个promise
我们知道了一个promise内容至少包含以上那些内容,所以一个简单的promise内部至少是这样的
class?myPromise?{
????static?PENDING?=?'pending'
????static?FULFILLEd?=?'fulfilled'
????static?REJECTED?=?'rejected'
????constructor(init){
????????this.state?=?myPromise.PENDING?//?promise状态
????????this.promiseRes?=?null??//?promise返回值
????????const?resolve?=?result=>{
????????//...
????????}
????????const?reject?=?result=>{
???????????//...
????????}
????????try{
????????????init(resolve,reject)??//?init就是初始化执行器
????????}catch(err){
????????????reject(err)
????????}
????????
????}
????then(onFulfilled,onRejected){
???????//...
????}
???catch(onRejected){
??????//...
????}
}
OK,大概了解之后,我们再来一个一个的看里面每个部分的实现以及作用
Promise的执行器
它其实是我们在new Promise
时传入的一个回调函数,这个函数本身是同步的,也就是说在new Promise
时它就会执行,这也是我们操作promise的入口。
class?myPromise{
??//...
??constructor(init){
????????try{
????????????init(resolve,reject)??//?init就是初始化执行器
????????}catch(err){
????????????reject(err)?//这里主要是在init执行器函数出错时,用以让promise状态变为rejected
????????}?
????}
??//...
}
该函数接受两个回调函数(resolve,reject)作为参数,用以改变Promise的状态
resolve与reject方法
这两个函数作为参数传到执行器函数中,用以后续改变Promise状态
class?myPromise?{
????static?PENDING?=?'pending'
????static?FULFILLEd?=?'fulfilled'
????static?REJECTED?=?'rejected'
????constructor(init){
????????this.state?=?myPromise.PENDING?//?promise状态
????????this.promiseRes?=?null??//?promise返回值
????????this.resolveCallback?=?[]?//成功回调集合
????????this.rejectCallback?=?[]?//失败回调集合
????????const?resolve?=?result=>{
????????????//?只有当状态为pending时才改变,保证状态一旦改变就不会再变
????????????if(this.state?===?myPromise.PENDING){
????????????????this.state?=?myPromise.FULFILLEd?//改变状态
????????????????this.promiseRes?=?result?//返回值
????????????????//依次调用成功回调
????????????????this.resolveCallback.forEach(fn=>fn())
????????????}
????????}
????????const?reject?=?result=>{
????????????//?只有当状态为pending时才改变,保证状态一旦改变就不会再变
????????????if(this.state?===?myPromise.PENDING){
????????????????this.state?=?myPromise.REJECTED?//改变状态
????????????????this.promiseRes?=?result?//返回值
????????????????//?依次调用失败回调
????????????????this.rejectCallback.forEach(fn=>fn())
????????????}
????????}
????????try{
????????????init(resolve,reject)??//?注意this指向
????????}catch(err){
????????????reject(err)
????????}
????????
????}
}
初步then方法
class?myPromise?{
????static?PENDING?=?'pending'
????static?FULFILLEd?=?'fulfilled'
????static?REJECTED?=?'rejected'
????constructor(init){
????????this.state?=?myPromise.PENDING?//?promise状态
????????this.promiseRes?=?null??//?promise返回值
????????this.resolveCallback?=?[]?//成功回调集合
????????this.rejectCallback?=?[]?//失败回调集合
????????const?resolve?=?result=>{
????????????//?只有当状态为pending时才改变,保证状态一旦改变就不会再变
????????????if(this.state?===?myPromise.PENDING){
????????????????this.state?=?myPromise.FULFILLEd?//改变状态
????????????????this.promiseRes?=?result?//返回值
????????????????//依次调用成功回调
????????????????this.resolveCallback.forEach(fn=>fn())
????????????}
????????}
????????const?reject?=?result=>{
????????????//?只有当状态为pending时才改变,保证状态一旦改变就不会再变
????????????if(this.state?===?myPromise.PENDING){
????????????????this.state?=?myPromise.REJECTED?//改变状态
????????????????this.promiseRes?=?result?//返回值
????????????????//?依次调用失败回调
????????????????this.rejectCallback.forEach(fn=>fn())
????????????}
????????}
????????try{
????????????init(resolve,reject)??//?注意this指向
????????}catch(err){
????????????reject(err)
????????}
????????
????}
????then(onFulfilled,onRejected){
????????if(this.state?===?myPromise.FULFILLEd?&&?typeof?onFulfilled?===?'function')?{
????????????onFulfilled(this.promiseRes)
????????}
????????if(this.state?===?myPromise.REJECTED?&&?typeof?onRejected?===?'function')?{
????????????onRejected(this.promiseRes)
????????}
????}
}
写到这里,我们的promise已经初步成型了,我们可以来测试一下:
const?res1?=?new?myPromise((res,rej)=>{
????res('成功啦~')
????rej('失败啦~')
})
res1.then((res)=>{
????console.log(res)
},err=>{
????console.log(err)
})
//?按照预期,这里应该是只会打印出成功啦~
从上图看我们,是不是符合我们的预期,并且myPromise
内部与原生的Promise
也是非常相似的。你们是不是觉得这里已经没问题了,上面我们只是测了一下同步方法的执行,但别忘了,Promise主要是来解决异步问题的,我们再来试一下里面执行异步方法还符不符合我们的预期?
const?res1?=?new?myPromise((res,rej)=>{
????setTimeout(()=>res('成功啦~'),1000)
????//?rej('失败啦~')
})
res1.then((res)=>{
????console.log(res)
})
这里我们预期本来是一秒之后打印成功啦,但它并没有如我们所愿,反而是什么也没打印出来,这是因为在setTimeout执行之前(pending)这个then方法已经执行过了,1s后状态变成fulfilled时,then也不会再执行了。
「所以我们需要保证then方法的回调函数在promise状态变成fulfilled
或rejected
时再执行,那么当promise状态为pending
时我们先要把回调存在对应的队列中,等后续状态改变后再执行」
较完整then方法
OK,这里我们修改一下我们的then方法,让其保证异步代码执行的正确性?(具体实现微任务我们可以用 mutationObserver,这里我们就用setTimeout来模拟一下)
class?myPromise?{
????static?PENDING?=?'pending'
????static?FULFILLEd?=?'fulfilled'
????static?REJECTED?=?'rejected'
????constructor(init){
????????this.state?=?myPromise.PENDING?//?promise状态
????????this.promiseRes?=?null??//?promise返回值
????????this.resolveCallback?=?[]?//成功回调集合
????????this.rejectCallback?=?[]?//失败回调集合
????????const?resolve?=?result=>{
????????????//?只有当状态为pending时才改变,保证状态一旦改变就不会再变
????????????if(this.state?===?myPromise.PENDING){
????????????????this.state?=?myPromise.FULFILLEd?//改变状态
????????????????this.promiseRes?=?result?//返回值
????????????????//依次调用成功回调
????????????????this.resolveCallback.forEach(fn=>fn())
????????????}
????????}
????????const?reject?=?result=>{
????????????//?只有当状态为pending时才改变,保证状态一旦改变就不会再变
????????????if(this.state?===?myPromise.PENDING){
????????????????this.state?=?myPromise.REJECTED?//改变状态
????????????????this.promiseRes?=?result?//返回值
????????????????//?依次调用失败回调
????????????????this.rejectCallback.forEach(fn=>fn())
????????????}
????????}
????????try{
????????????init(resolve,reject)??//?注意this指向
????????}catch(err){
????????????reject(err)
????????}
????????
????}
????then(onFulfilled,onRejected){
????????if(this.state?===?myPromise.FULFILLEd?&&?typeof?onFulfilled?===?'function')?{
????????????onFulfilled(this.promiseRes)
????????}
????????if(this.state?===?myPromise.REJECTED?&&?typeof?onRejected?===?'function')?{
????????????onRejected(this.promiseRes)
????????}
????????if(this.state?===?myPromise.PENDING){
????????????if(onFulfilled?&&?typeof?onFulfilled?===?'function'){
????????????????this.resolveCallback.push(()=>
????????????????//?这里我们用setTimeout来模拟实现then的微任务
????????????????setTimeout(()=>{
????????????????????onFulfilled(this.promiseRes)
????????????????},0)
????????????????)
????????????}
????????????if(onRejected?&&?typeof?onRejected?===?'function'){
????????????????this.rejectCallback.push(()=>
????????????????//?这里我们用setTimeout来模拟实现then的微任务
????????????????setTimeout(()=>{
????????????????????onRejected(this.promiseRes)
????????????????},0)
????????????????)
????????????}
????????}
????}
}
这里我们可以再测试一下上面那个异步函数的测试用例,发现它能够正确打印,OK,一个较完整的then方法就算实现了~
then的链式调用
then
方法会返回一个新的Promise
(??注意:不是原来的那个Promise
)所以可以采用链式调用
采用链式的then
,可以指定一组按照次序调用的回调函数。这时,前一个回调函数,有可能返回的还是一个Promise
对象(即有异步操作),这时后一个回调函数,就会等待该Promise
对象的状态发生变化,才会被调用。
then(onFulfilled,onRejected){
????????const?{promiseRes,state}?=?this
????????let?promise?=?new?myPromise((reso,reje)=>{
????????????const?resolveMyPromise?=?promiseRes?=>?{
????????????????try{
????????????????????if(typeof?onFulfilled?!==?'function'){
????????????????????????//?如果then的第一个回调不是一个函数,直接忽略,返回一个新的promise
????????????????????????reso(promiseRes)
????????????????????}else{
????????????????????????//?获取第一个回调的执行结果
????????????????????????const?res?=?onFulfilled(promiseRes)
????????????????????????//?看该执行结果是否是一个promise
????????????????????????if(res?instanceof?myPromise){
????????????????????????????//?是一个promise,等它状态改变后再改变then返回的promise状态
????????????????????????????res.then(reso,rej)?
????????????????????????}else{
????????????????????????????//?不是一个promise,将它作为新的promise的resolve
????????????????????????????reso(res)
????????????????????????}
????????????????????}
????????????????}catch(err){
????????????????????//异常,直接将新的promise状态置为rejected
????????????????????reje(err)
????????????????}
????????????}
????????????const?rejectMyPromise?=?promiseRes?=>?{
????????????????try{
????????????????????if(typeof?onRejected?!==?'function'){
????????????????????????//?如果then的第二个回调不是一个函数,直接忽略,返回一个新的promise
????????????????????????reje(promiseRes)
????????????????????}else{
????????????????????????//?获取第二个回调的执行结果
????????????????????????const?res?=?onRejected(promiseRes)
????????????????????????//?看该执行结果是否是一个promise
????????????????????????if(res?instanceof?myPromise){
????????????????????????????//?是一个promise,等它状态改变后再改变then返回的promise状态
????????????????????????????res.then(reso,rej)?
????????????????????????}else{
????????????????????????????//?不是一个promise,将它作为新的promise的resolve
????????????????????????????reje(res)
????????????????????????}
????????????????????}
????????????????????
????????????????}catch(err){
????????????????????//异常,直接将新的promise状态置为rejected
????????????????????reje(err)
????????????????}
????????????}
????????????if(state?===?myPromise.FULFILLEd)?{
????????????????resolveMyPromise(promiseRes)
????????????}
????????????if(state?===?myPromise.REJECTED)?{
????????????????rejectMyPromise(promiseRes)
????????????}
????????????if(state?===?myPromise.PENDING){
????????????????if(onFulfilled?&&?typeof?onFulfilled?===?'function'){
????????????????????this.resolveCallback.push(()=>
????????????????????//?这里我们用setTimeout来模拟实现then的微任务
????????????????????setTimeout(()=>{
????????????????????????resolveMyPromise(this.promiseRes)
????????????????????},0)
????????????????????)
????????????????}
????????????????if(onRejected?&&?typeof?onRejected?===?'function'){
????????????????????this.rejectCallback.push(()=>
????????????????????//?这里我们用setTimeout来模拟实现then的微任务
????????????????????setTimeout(()=>{
????????????????????????rejectMyPromise(this.promiseRes)
????????????????????},0)
????????????????????)
????????????????}
????????????}
????????})
????????return?promise
????}
catch方法
我们知道then的第二个回调其实与catch方法是一样的,所以catch方法我们可以这样实现
catch(onRejected)?{
????????return?this.then(undefined,onRejected)
????}
Promise.resolve
将对象转为一个promise对象,根据参数不通可分为四种情况
-
参数是一个Promise实例,直接返回该实例
-
参数是一个
thenable
对象,将该对象转为Promise对象后,执行该对象的then
方法 -
没有参数,也是返回一个状态为
resolved
的新的Promise对象 -
参数是一个一个原始值,返回一个新的Promise对象,状态为
resolved
static?resolve(v){
??//1.参数是一个Promise实例,直接返回
??if(v?instanceof?myPromise){
????return?v
??}
??//2.参数是一个thenable对象,转为Promise后执行该对象的then方法
??if(typeof?v?===?'object'?&&?typeof?v.then?===?'function'){
????return?new?myPromise((res,rej)=>{
??????v.then(res,rej)
????})
??}
??//3.没有参数,直接返回一个resolved状态的promise
??if(!v){
????return?new?myPromise(res=>{
??????res()
????})
??}
??//4.参数是一个原始值,返回一个新的Promise,状态为resolved
??return?new?myPromise(res=>{
????res(v)
??})
}
Promise.reject
返回一个新的Promise对象,状态为rejected
static?reject(v){
??return?new?myPromise((res,rej)=>{
????rej(v)
??})
}
Promise.all
该方法用于将多个Promise实例包装成一个新的Promise实例,如果有不是Promise的项,则让该项直接成功
const?p?=?Promise.all([p1,p2,p3])
p
的状态由p1
、p2
、p3
决定,分成两种情况。
(1)只有p1
、p2
、p3
的状态都变成fulfilled
,p
的状态才会变成fulfilled
,此时p1
、p2
、p3
的返回值组成一个数组,传递给p
的回调函数。
(2)只要p1
、p2
、p3
之中有一个被rejected
,p
的状态就变成rejected
,此时第一个被reject
的实例的返回值,会传递给p
的回调函数。
Ok,了解完Promise.all
我们动手来实现一遍
static?all?(promises){
????????return?new?myPromise((res,rej)=>{
????????????let?count?=?0
????????????const?result?=?[];
????????????function?addFun(index,resf)?{
????????????????result[index]=resf?//?这里用索引别用push,保证返回的顺序
????????????????count++
????????????????if(count==promises.length)?{
????????????????????res(result)
????????????????}
????????????}
????????????[].forEach.call(promises,(promise,index)=>{
????????????????if(promise?instanceof?myPromise)?{
????????????????????promise.then(success=>{
????????????????????????//?count?++
????????????????????????//?result.push(success)
????????????????????????addFun(index,success)
????????????????????},err=>{
????????????????????????rej(err)
????????????????????})
????????????????}else{
????????????????????addFun(index,promise)
????????????????}
????????????})
????????})
????}
Promise.race
Promise.race()
方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。
const?p?=?Promise.race([p1,?p2,?p3]);
上面代码中,只要p1
、p2
、p3
之中有一个实例率先改变状态,p
的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p
的回调函数。
static?race(promises)?{
????????return?new?myPromise((res,rej)=>{
????????????[].forEach.call(promises,promise=>{
????????????????if(promise?instanceof?myPromise){
????????????????????promise.then(success=>{
????????????????????????res(success)
????????????????????},error=>{
????????????????????????rej(error)
????????????????????})
????????????????}else{
????????????????????res(promise)
????????????????}?
????????????})
????????})
????}
完整代码
class?myPromise?{
????static?PENDING?=?'pending'
????static?FULFILLEd?=?'fulfilled'
????static?REJECTED?=?'rejected'
????constructor(init){
????????this.state?=?myPromise.PENDING?//?promise状态
????????this.promiseRes?=?null??//?promise返回值
????????this.resolveCallback?=?[]?//成功回调集合
????????this.rejectCallback?=?[]?//失败回调集合
????????const?resolve?=?result=>{
????????????//?只有当状态为pending时才改变,保证状态一旦改变就不会再变
????????????if(this.state?===?myPromise.PENDING){
????????????????this.state?=?myPromise.FULFILLEd?//改变状态
????????????????this.promiseRes?=?result?//返回值
????????????????//依次调用成功回调
????????????????this.resolveCallback.forEach(fn=>fn())
????????????}
????????}
????????const?reject?=?result=>{
????????????//?只有当状态为pending时才改变,保证状态一旦改变就不会再变
????????????if(this.state?===?myPromise.PENDING){
????????????????this.state?=?myPromise.REJECTED?//改变状态
????????????????this.promiseRes?=?result?//返回值
????????????????//?依次调用失败回调
????????????????this.rejectCallback.forEach(fn=>fn())
????????????}
????????}
????????try{
????????????init(resolve,reject)??//?注意this指向
????????}catch(err){
????????????reject(err)
????????}
????????
????}
????then(onFulfilled,onRejected){
????????const?{promiseRes,state}?=?this
????????let?promise?=?new?myPromise((reso,reje)=>{
????????????const?resolveMyPromise?=?promiseRes?=>?{
????????????????try{
????????????????????if(typeof?onFulfilled?!==?'function'){
????????????????????????//?如果then的第一个回调不是一个函数,直接忽略,返回一个新的promise
????????????????????????reso(promiseRes)
????????????????????}else{
????????????????????????//?获取第一个回调的执行结果
????????????????????????const?res?=?onFulfilled(promiseRes)
????????????????????????//?看该执行结果是否是一个promise
????????????????????????if(res?instanceof?myPromise){
????????????????????????????//?是一个promise,等它状态改变后再改变then返回的promise状态
????????????????????????????res.then(reso,rej)?
????????????????????????}else{
????????????????????????????//?不是一个promise,将它作为新的promise的resolve
????????????????????????????reso(res)
????????????????????????}
????????????????????}
????????????????}catch(err){
????????????????????//异常,直接将新的promise状态置为rejected
????????????????????reje(err)
????????????????}
????????????}
????????????const?rejectMyPromise?=?promiseRes?=>?{
????????????????try{
????????????????????if(typeof?onRejected?!==?'function'){
????????????????????????//?如果then的第二个回调不是一个函数,直接忽略,返回一个新的promise
????????????????????????reje(promiseRes)
????????????????????}else{
????????????????????????//?获取第二个回调的执行结果
????????????????????????const?res?=?onRejected(promiseRes)
????????????????????????//?看该执行结果是否是一个promise
????????????????????????if(res?instanceof?myPromise){
????????????????????????????//?是一个promise,等它状态改变后再改变then返回的promise状态
????????????????????????????res.then(reso,rej)?
????????????????????????}else{
????????????????????????????//?不是一个promise,将它作为新的promise的resolve
????????????????????????????reje(res)
????????????????????????}
????????????????????}
????????????????????
????????????????}catch(err){
????????????????????//异常,直接将新的promise状态置为rejected
????????????????????reje(err)
????????????????}
????????????}
????????????if(state?===?myPromise.FULFILLEd)?{
????????????????resolveMyPromise(promiseRes)
????????????}
????????????if(state?===?myPromise.REJECTED)?{
????????????????rejectMyPromise(promiseRes)
????????????}
????????????if(state?===?myPromise.PENDING){
????????????????if(onFulfilled?&&?typeof?onFulfilled?===?'function'){
????????????????????this.resolveCallback.push(()=>
????????????????????//?这里我们用setTimeout来模拟实现then的微任务
????????????????????setTimeout(()=>{
????????????????????????resolveMyPromise(this.promiseRes)
????????????????????},0)
????????????????????)
????????????????}
????????????????if(onRejected?&&?typeof?onRejected?===?'function'){
????????????????????this.rejectCallback.push(()=>
????????????????????//?这里我们用setTimeout来模拟实现then的微任务
????????????????????setTimeout(()=>{
????????????????????????rejectMyPromise(this.promiseRes)
????????????????????},0)
????????????????????)
????????????????}
????????????}
????????})
????????return?promise
????}
????catch(onRejected)?{
????????return?this.then(undefined,onRejected)
????}
????static?all?(promises){
????????return?new?myPromise((res,rej)=>{
????????????let?count?=?0
????????????const?result?=?[];
????????????function?addFun(index,resf)?{
????????????????result[index]=resf?//?这里用索引别用push,保证返回的顺序
????????????????count++
????????????????if(count==promises.length)?{
????????????????????res(result)
????????????????}
????????????}
????????????[].forEach.call(promises,(promise,index)=>{
????????????????if(promise?instanceof?myPromise)?{
????????????????????promise.then(success=>{
????????????????????????addFun(index,success)
????????????????????},err=>{
????????????????????????rej(err)
????????????????????})
????????????????}else{
????????????????????addFun(index,promise)
????????????????}
????????????})
????????})
????}
????static?race(promises)?{
????????return?new?myPromise((res,rej)=>{
????????????[].forEach.call(promises,promise=>{
????????????????if(promise?instanceof?myPromise){
????????????????????promise.then(success=>{
????????????????????????res(success)
????????????????????},error=>{
????????????????????????rej(error)
????????????????????})
????????????????}else{
????????????????????res(promise)
????????????????}?
????????????})
????????})
????}
????static?resolve(v){
????????//1.参数是一个Promise实例,直接返回
????????if(v?instanceof?myPromise){
????????????return?v
????????}
????????//2.参数是一个thenable对象,转为Promise后执行该对象的then方法
????????if(typeof?v?===?'object'?&&?typeof?v.then?===?'function'){
????????????return?new?myPromise((res,rej)=>{
????????????????v.then(res,rej)
????????????})
????????}
????????//3.没有参数,直接返回一个resolved状态的promise
????????if(!v){
????????????return?new?myPromise(res=>{
????????????????res()
????????????})
????????}
????????//4.参数是一个原始值,返回一个新的Promise,状态为resolved
????????return?new?myPromise(res=>{
????????????res(v)
????????})
????}
????static?reject(v){
????????return?new?myPromise((res,rej)=>{
????????????rej(v)
????????})
????}
}
总结
OK,上面跟大家一起过了一遍Promise
的用法以及自己动手实现了一遍Promise
,想必看完这篇文章,大家对Promise
会有一个更加清晰的认识。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!