# Promise

Promise 对象用于表示一个异步操作的最终完成或者失败

本质上 Promise 是一个函数返回的对象,我们可以在它上面绑定回调函数,这样就不需要在一开始把回调函数作为参数传入这个函数中了

案例 1:将回调函数作为参数传入


// 成功的回调函数
function successCallback(result) {
  console.log("音频文件创建成功:" + result);
}

// 失败的回调函数
function failureCallback(error) {
  console.log("音频文件创建失败:" + error);
}

createAudioFileAsync(audioSettings, successCallback, failureCallback)

案例 2: 使用 Promise,将回调函数绑定在 Pormise 上


const promise = createAudioFileAsync(audioSettings);
promise.then(successCallback, failureCallback);

或者简写为:

createAudioFileAsync(audioSettings).then(successCallback, failureCallback);

# 约定:

不同于 “老式” 的传入回调,在使用 Promise 时,会有如下约定:

在本轮 “事件循环” 运行完成之前,回调函数是不会被调用的
即使异步操作已经完成(成功或失败),在这之后通过then(). 添加的回调函数也会被调用
通过多次调用then(). 可以添加多个回调函数,他们会按照插入顺序进行执行

# 链式调用

const promise2 = doSomething().then(successCallback, failureCallback);

promise2 不仅表示 doSomething () 函数的完成,也代表了你传入的 successCallback 或者 failureCallback 的完成。这两个函数也可以返回一个 Promise 对象,从而形成另一个异步操作,这样的话,在 promise 上新增的回调函数会排在这个 Promise 对象后面

案例:Promise 链式调用的样例


function fun3() {
    return new Promise((resolve) => {
        setTimeout(() => {
            const str = 'console.log====fun3';
            console.log(str)
            resolve(str)
        }, 500)
    })
}

function fun() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            const str = 'console.log====fun';
            console.log(str)
            reject(str)
            // resolve(str)
        }, 500)
    })
}

const promise = fun()
const p1 = promise.then((suc) => {
    console.log('suc===', suc)
    console.log('算是成功了')
}, (ero) => {
    console.log('ero===', ero)
    console.log('失败了啊!')
    // return '失败是成功之母'
    // 注意下边的fun3()函数的调用方式,一种是作为普通函数调用,另一种是作为返回值调用,效果是不同的
    // fun3()
    return fun3()
})
const p2 = p1.then((suc2) => {
    console.log('再让我成功一次', suc2)
}, (ero2) => {
    console.log('失去的下次一定全部拿回来', ero2)
})

结果:


console.log====fun
ero=== console.log====fun
失败了啊!
console.log====fun3
再让我成功一次 console.log====fun3

在上述代码中,promise 的失败回调函数中,也返回了一个 Promise 对象,从而形成了另一个异步操作。因此在 p1 上新增的回调函数会排在这个 Promise 对象的后面。— 也印证了上边的结论

基本上,每一个 Promise 都代表了链中另一个异步过程的完成

then 里的参数是可选的,catch (failureCallback) 是 then (null, failureCallback) 的缩略形式。

** 注意:** 一定要有返回值,否则,callback 将无法获取上一个 Promise 的结果。(如果使用箭头函数,() => x 比 () => { return x; } 更简洁一些,但后一种保留 return 的写法才支持使用多个语句。)。

# Catch 的后续链式操作

通常,一遇到异常抛出,浏览器就会顺着 Promise 链寻找下一个 onRejected 失败回调函数或者由 .catch () 指定的回调函数。这和以下同步代码的工作原理(执行过程)非常相似。


try {
  let result = syncDoSomething();
  let newResult = syncDoSomethingElse(result);
  let finalResult = syncDoThirdThing(newResult);
  console.log(`Got the final result: ${finalResult}`);
} catch(error) {
  failureCallback(error);
}

# Promise 拒绝事件