SOURCE

/**
 *
 * Promise是ES6引入的异步编程解决方案,用于处理异步操作。它代表一个未来才会知道结果的值,可以将异步操作以同步的流程表达出来,
 避免回调地狱。
Promise 三种状态
Pending(进行中):初始状态
Fulfilled(已成功):操作成功完成
Rejected(已失败):操作失败
状态特点:
状态只能从 Pending → Fulfilled 或 Pending → Rejected
状态一旦改变就不会再变,任何时候都可以得到这个结果
 一、Promise 实例方法
 1. then(onFulfilled成功回调函数, onRejected失败回调函数)
 2. catch(onRejected失败回调函数):捕获错误
 3. finally(onFinally回调函数):无论成功失败都会执行,常用于关闭加载动画、释放资源等
 * 
 二、Promise 静态方法
 1. Promise.resolve():返回一个已成功的 Promise 对象
Promise.resolve('success').then(result => console.log(result)); // 将值转换为 fulfilled 状态的 Promise
 等价于
new Promise(resolve => resolve('success'));
 2. Promise.reject():返回一个已失败的 Promise 对象
Promise.reject(new Error('失败')).catch(error => console.error(error)); // 返回rejected 状态的 Promise
 3. Promise.all([p1, p2, p3]):并行执行多个 Promise,全部成功才成功,只要有一个失败,就会进入 catch。并行请求多个接口
 4. Promise.allSettled([p1, p2]):等待所有 Promise 完成(无论成功失败)
 5. Promise.race([p1, p2]): 返回最快完成的 Promise(无论成功失败)
 6. Promise.any([p1, p2]):返回第一个成功的 Promise,全部失败才失败

 * 什么时候使用Promise
 * 1.先异步,后处理
 * 
 * 为什么用Promise
 * 解决回调地狱问题,实现每一步操作的分离
 * 
 * 
 * 有先一步操作(它是一个异步操作,需要过一段时间才能完成),之后再进行下一步操作
 */
function getInfo(name) {
    let xhr = new XMLHttpRequest()
    //异步操作,回调函数
    xhr.onloadend = function() {
        let data = JSON.parse(xhr.responseText)
        console.log(data)
        return data
    }
    xhr.open('GET',`http://xxx?sname=${name}`)
    xhr.send()
}
let res = getInfo('zhangsan')
console.log(res)//这里res是undefined

//用Promise解决
function getInfo(name) {
 return new Promise((resolve,reject)=> {
    let xhr = new XMLHttpRequest()
    xhr.onloadend = function() {
        let data = JSON.parse(xhr.responseText)
        if(data) {
            resolve(data)
        }else {
            reject('没有得到数据')
        }
    }
    xhr.open('GET',`http://xxx?sname=${name}`)
    xhr.send()
})
}
let resPromise = getInfo('zhangsan')
resPromise.then(showTable)
function showTable(data) {
   let str=`<table>
   <tr>
   <th>编号</th>
   <th>姓名</th>
   </tr>`
   str+=data.map(item=>`<tr>
   <td>${item.sid}</td>
    <td>${item.sname}</td>
   </tr>`).join('')
   str+='</table>' 
}
//_----需求:第一步:根据学生名称查找他的信息。第二步:再根据学生信息中编号查询他的成绩。第三步:根据成绩信息中的id查询判卷老师
function getData(sname) {
    return new Promise((resolve,reject)=>{
        let xhr = new XMLHttpRequest()
        xhr.onloadend = function() {
        let data = JSON.parse(xhr.responseText)
        if(data) {
            resolve(data[0].sid)
        }else {
            reject('没有查询到个人信息')
        }
    }
    xhr.open('GET',`http://xxx?sname=${sname}`)
    xhr.send()

    })

}

function getScore(sid) {
    return new Promise((resolve,reject)=>{
        let xhr = new XMLHttpRequest()
        xhr.onloadend = function() {
        let score = JSON.parse(xhr.responseText)
        if(score) {
            resolve(score.tid)
        }else {
            reject('没有查询到成绩')
        }
    }
    xhr.open('GET',`http://xxx?sid=${sid}`)
    xhr.send()

    })

}

function getTeacher(tid) {
    return new Promise((resolve,reject)=>{
        let xhr = new XMLHttpRequest()
        xhr.onloadend = function() {
        let teacher = JSON.parse(xhr.responseText)
        if(teacher) {
            console.log('查询到老师',teacher)
        }else {
            reject('没有找到老师信息')
        }
       
    }
    xhr.open('GET',`http://xxx?tid=${tid}`)
    xhr.send()

    })

}
//----用Promise
getData('张宁')
       .then(getScore)
       .then(getTeacher)
       .catch((reason)=>{
           console.log('捕获到报错',reason)
       })

//----用async/await  用同步代码的方式写异步代码
async function getResult(sname) {
let sid = await getData(sname)
let tid = await getScore(sid)
let teacher = await getTeacher(tid)
}
getResult('郭晓晓').catch((reason)=>{
           console.log('捕获到报错',reason)
       })


//-------------------Promise静态方法详解
1.Promise.all
参数: 接收一个可迭代对象(如数组),通常包含多个Promise。
​行为: 它返回一个新的Promise。当所有输入的Promise都成功完成(fulfilled)时,它才成功,结果是一个数组,按输入顺序收集所有成功值。如果其中任何一个Promise失败(rejected),它会立即失败,并返回这个失败的原因
​使用场景: 适用于多个强依赖的异步任务必须全部成功的场景。
​示例: 一个页面需要同时加载用户基本信息、好友列表和消息通知,这三部分数据都获取成功后才能渲染页面
async function getAll() {
    const [userInfo,friends,messages] = await Promise.all([fetch('/api/user'),fetch('/api/friends'),fetch('/api/messages')])  
}
2.Promise.allSettled
​参数: 一个可迭代对象。
​行为: 它会等待所有输入的Promise都“敲定”(settled,即要么成功要么失败)。它自己永远不会失败,总是成功返回一个对象数组。每个对象都有一个status字段('fulfilled'或 'rejected'),成功对象有value属性,失败对象有reason属性
​使用场景: 适用于需要了解每个异步任务最终结果的情况,特别是当部分失败不影响整体流程时。
示例: 批量上传多个文件,需要知道每个文件是上传成功还是失败,以便对失败的文件进行重试或提示

const results = await Promise.allSettled([
    uploadFile(file1),
    uploadFile(file2),
    uploadFile(file3)
]);
const successfulUploads = results.filter(r => r.status === 'fulfilled');
const failedUploads = results.filter(r => r.status === 'rejected');
3.Promise.any
​参数: 一个可迭代对象。
​行为: 当输入的Promise中有任何一个成功(fulfilled),它就会立即成功,并返回那个成功的值。只有当所有的Promise都失败时,它才会失败,并返回一个AggregateError,其中包含所有失败的原因
​使用场景: 适用于从多个来源获取相同资源,​只要有一个成功即可的场景,常用于提高可用性和冗余备份。
​示例: 从多个镜像服务器请求同一个资源,使用最先响应的那个。
const fastestResponse = await Promise.any([
    fetch('https://mirror1.com/data'),
    fetch('https://mirror2.com/data'),
    fetch('https://mirror3.com/data')
]);
4. Promise.race
​参数: 一个可迭代对象。
​行为: 它采纳第一个“敲定”(settled)​​的Promise的结果,无论这个结果是成功还是失败。后续Promise的结果会被忽略。
​使用场景:
​设置超时控制: 为一个异步操作设置时间限制。
// 如果 fetchData 在5秒内没有响应,则触发超时
const dataOrTimeout = await Promise.race([
    fetchData(),
    new Promise((_, reject) => setTimeout(() => reject(new Error('Timeout')), 5000))
]);
console 命令行工具 X clear

                    
>
console