Javascript Promise

Promise


系列文章

这是JavaScript系列文章:



promise构造函数

  • 主要作用是包装还未支持 promises 的函数

  • promise 并不是立即返回最终执行结果,而是一个能代表未来出现的结果的promise对象

  • promise 的几种状态:

    • pending 初始状态,既不是成功,也不是失败状态。
    • fulfilled 意味着操作成功完成。
    • rejected 意味着操作失败。
      promise
  • 基础语法
    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 传出的拒绝原因

  • 返回值

    返回值状态codePromise状态参数值
    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); // 不会执行
    });
    

鸣谢

  1. MDN

    1. Promise
    2. 使用Promise
    3. then()
    4. catch()
    5. resolve()
    6. reject()
  2. 阮一峰

    1. Promise对象
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值