Promise
系列文章
这是JavaScript
系列文章:
promise构造函数
-
主要作用是包装还未支持
promises
的函数 -
promise
并不是立即返回最终执行结果,而是一个能代表未来出现的结果的promise对象 -
promise
的几种状态:pending
初始状态,既不是成功,也不是失败状态。fulfilled
意味着操作成功完成。rejected
意味着操作失败。
-
基础语法
new Promise( function(resolve, reject) {...} /* executor */ );
resolve
成功的时候执行,返回Promise对象,可以被链式调用reject
失败的时候执行,resolve的返回值被忽略。返回Promise对象,可以被链式调用
-
DEMO
const myFirstPromise = new Promise((resolve, reject) => { // *** // 这里做一些异步操作,最终会调用下面两个函数 // *** // resolve(someValue); // fullfilled // 或 // reject('failure reason'); // rejected });
-
示例一
let promise1 = new Promise(function(resolve, reject) { // 当异步代码执行成功时,我们才会调用resolve(...), 当异步代码失败时就会调用reject(...) // 在本例中,我们使用setTimeout(...)来模拟异步代码,实际编码时可能是XHR请求或是HTML5的一些API方法. setTimeout(function() { resolve('foo'); }, 3000); }); promise1.then(function(value) { // value的值是上面调用resolve(...)方法传入的值. // value参数不一定非要是字符串类型,这里只是举个例子 console.log(value); // expected output: "foo" }); console.log(promise1); // expected output: [Object Promise]
-
示例二
function imgLoad(url) { // Create new promise with the Promise() constructor; // This has as its argument a function // with two parameters, resolve and reject return new Promise(function(resolve, reject) { // Standard XHR to load an image var request = new XMLHttpRequest(); request.open('GET', url); request.responseType = 'blob'; // When the request loads, check whether it was successful request.onload = function() { if (request.status === 200) { // If successful, resolve the promise by passing back the request response resolve(request.response); } else { // If it fails, reject the promise with a error message reject(Error('Image didn\'t load successfully; error code:' + request.statusText)); } }; request.onerror = function() { // Also deal with the case when the entire request fails to begin with // This is probably a network error, so reject the promise with an appropriate message reject(Error('There was a network error.')); }; // Send the request request.send(); }); } // Get a reference to the body element, and create a new image object var body = document.querySelector('body'); var myImage = new Image(); // Call the function with the URL we want to load, but then chain the // promise then() method on to the end of it. This contains two callbacks imgLoad('myLittleVader.jpg').then(function(response) { // The first runs when the promise resolves, with the request.response // specified within the resolve() method. var imageURL = window.URL.createObjectURL(response); myImage.src = imageURL; body.appendChild(myImage); // The second runs when the promise // is rejected, and logs the Error specified with the reject() method. }, function(Error) { console.log(Error); });
-
示例三
-
.then
内部的第二个参数是失败的时候执行,.catch
也是失败的时候执行,两个的区别?答案:哪个在前执行哪个
// catch: error reason // then suc undefined let promise1 = new Promise(function(resolve, reject) { setTimeout(function() { reject('error reason'); }, 3000); }); promise1 .catch(err => { console.log('catch: ', err); }) .then( function(value) { console.log('then suc: ', value); // expected output: "foo" 过了3秒才会执行 }, function(err) { console.log('then err: ', err); } );
// then err: error reason let promise1 = new Promise(function(resolve, reject) { setTimeout(function() { reject('error reason'); }, 3000); }); promise1 .then( function(value) { console.log('then suc: ', value); // expected output: "foo" 过了3秒才会执行 }, function(err) { console.log('then err: ', err); } ) .catch(err => { console.log('catch: ', err); });
MDN答案
then里的参数是可选的,catch(failureCallback)
是then(null, failureCallback)
的缩略形式。// 箭头函数 doSomething() .then(result => doSomethingElse(result)) .then(newResult => doThirdThing(newResult)) .then(finalResult => { console.log(`Got the final result: ${finalResult}`); }) .catch(failureCallback);
注意:如果想要在回调中获取上个 Promise 中的结果,上个 Promise 中必须要返回结果。(使用
() => x
比() => { return x; }
更简洁一点).
-
使用Promises
- 通过多次调用 .then,可以添加多个回调函数,它们会按照插入顺序并且独立运行。
- Promise 最直接的好处就是链式调用。
链式调用
.then()
后面可以再连接一个 .then()
构成一条链,每一个 Promise 代表了链式中另一个异步过程的完成。
Catch在调用链
当在链式操作失败 catch
后,可以继续执行 .then()
// output:
// Initial
// Do that
// Do this whatever happened before
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');
});
方法
resolve
-
基础语法
Promise.resolve(value); // 默认为成功态,直接将value向调用链下传递 Promise.resolve(promise); Promise.resolve(thenable); // thenable 代表带有 then 方法
-
示例一:value
Promise.resolve("Success").then(function(value) { console.log(value); // "Success" }, function(value) { // 不会被调用 });
-
示例二:promise
let original = Promise.resolve('猜猜看,我是第几行'); let cast = Promise.resolve(original); cast.then(function(value) { console.log('value: ' + value); } console.log('original === cast ? ' + (original === cast));
-
示例三:thenable
// Resolve一个thenable对象 var p1 = Promise.resolve({ then: function(onFulfill, onReject) { onFulfill("fulfilled!"); } }); console.log(p1 instanceof Promise) // true, 这是一个Promise对象 p1.then(function(v) { console.log(v); // 输出"fulfilled!" }, function(e) { // 不会被调用 });
reject
- 基础语法
Promise.reject(reason);
- 示例一
Promise.reject("Testing static reject").then(function(reason) { // 未被调用 }, function(reason) { console.log(reason); // "Testing static reject" }); Promise.reject(new Error("fail")).then(function(result) { // 未被调用 }, function(error) { console.log(error); // stacktrace });
then
-
then
中如果没有处理相关回调的函数,那么会自动生成一个Promise
对象,以保证链式调用 -
基础语法
p.then(onFullFilled, onRejected); // OR p.then(function(value) { // fulfillment }, function(error) { // rejection });
-
参数
-
onFullFilled
函数,该函数有一个参数是resolve
传出的最终结果
如果传入的不是函数,替换为函数:(x) => x
,原样返回promise
最终结果的函数 -
onRejected
函数,该函数有一个参数是reject
传出的拒绝原因
-
-
返回值
返回值状态 code Promise状态 参数值 值 return
接受 返回值 抛出错误 throw new ...
拒绝 抛出的错误 接受 resolve
接受 接受的回调函数参数值 拒绝 reject
拒绝 拒绝的回调函数参数值 未定 ? 未定 与之前未定的参数值一致 -
示例一
所谓链式调用的完美展示:Promise .reject() .then( () => 99, () => 42 ) // onRejected returns 42 which is wrapped in a resolving Promise .then( solution => console.log( 'Resolved with ' + solution ) ); // Resolved with 42
.reject
表示拒绝态,输出42,之后的.then
照常执行
catch
.catch(onRejected)
其实内部调用的.then(undefined, onRejected)
- 基础语法
p.catch(onRejected); // OR p.catch(function(reason) { // 拒绝 }
throw 'oh, no!';
和return Promise.reject('oh, no!');
效果一致- 示例一:
在异步函数中抛出的错误不会被catch捕获到let p2 = new Promise(function(resolve, reject) { setTimeout(function() { throw 'Uncaught Exception!'; }, 1000); }); p2.catch(function(e) { console.log(e); // 不会执行 });