一个 Promise 就是一个对象,它代表了一个异步操作的最终完成或者失败(承载了回调函数执行完的结果的一个对象)。本质上,Promise 是一个绑定了回调的对象,而不是将回调传进函数内部。
假设,现有一个名为 createAudioFileAsync() 的函数,在给定的配置文件和两个回调函数的情况下,这个函数能异步地生成声音文件。传统写法如下:
// 成功的回调函数
function successCallback(result) {
console.log("声音文件创建成功: " + result);
}
// 失败的回调函数
function failureCallback(error) {
console.log("声音文件创建失败: " + error);
}
createAudioFileAsync(audioSettings, successCallback, failureCallback)
Promise对象最新的方式使得你可以将你的 callback 绑定在该 Promise上,如果函数createAudioFileAsync()被重写为返回Promise对象,就可以像这样简单的使用:
createAudioFileAsync(audioSettings).then(successCallback, failureCallback);
链式调用
当多个异步函数调用时,then() 函数会返回一个全新的 Promise,和原来的不同:
const promise = doSomething();
const promise2 = promise.then(successCallback, failureCallback);
//或者
const promise2 = doSomething().then(successCallback, failureCallback);
第二个对象(promise2)不仅代表doSomething()函数的完成,也代表了你传入的 successCallback 或者failureCallback 的完成successCallback 或 failureCallback 有可能返回一个Promise对象从而形成另一个异步操作。这样的话,任何一个 promise2 新增的回调函数都会被依次排在由上一个successCallback(成功回调函数) 或 failureCallback(失败回调函数) 执行后所返回的 Promise对象的后面。每一个 Promise 代表了链式中另一个异步过程的完成。
Promise 链:
doSomething().then(function(result) {
return doSomethingElse(result);
})
.then(function(newResult) {
return doThirdThing(newResult);
})
.then(function(finalResult) {
console.log('Got the final result: ' + finalResult);
})
.catch(failureCallback);
上面 catch(failureCallback) 是 then(null, failureCallback) 的缩略形式。
注意:一定要有返回(即 需要 return ),否则 callback 无法获取上个 Promise 的结果。(使用 () => x 比() => { return x; } 更简洁一点).
Catch 的后续链式操作
new Promise((resolve, reject) => {
console.log('Initial');
resolve();
})
.then(() => {
throw new Error('Something failed');
console.log('Do this');
})
.catch(() => {
console.log('Do that');
})
.then(() => {
console.log('Do this whatever happened before');
})
//输出结果如下:
Initial
Do that
Do this whatever happened before
注意:上面由于“Something failed”错误的抛出导致了失败回调函数的调用,所以“Do this”文本没有被输出。但是Catch 的后续调用操作还是继续进行
promise的某个状态一旦生成就结束,永久的不能再改变。
function test(){
return new Promise((resolve,reject)=>{
resolve('resolve-11111')
reject('reject-22222') //这个永远不会执行,因为上面的resolve已经执行返回
})
}
//调用生成Promise对象
test().then((res)=>{
console.log(res) //打印出 resolve-11111
}).catch((er)=>{
console.log(er) //如果上面的 resolve('resolve-11111')去掉,就打印出reject-22222
})
上述方法改造一下 套入请求ajax的请求,就有拥有promise功能,
function test(){
return new Promise((resolve,reject)=>{
const xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.onload = () => resolve(xhr.responseText);
xhr.onerror = () => reject(xhr.statusText);
xhr.send();
})
}
test().then((res)=>{
console.log(res) //打印出 请求返回结果
}).catch((er)=>{
console.log(er) //如果上面的onerror执行就打印出错误信息
})