关于javascript Promise对象

1.Promise简述:

Promise对象其实是一种对于异步操作的解决方案;
MDN的解释是这样的:Promise 对象用于表示一个异步操作的最终完成 (或失败), 及其结果值。


const promise1 = new Promise((resolve, reject) => {

  setTimeout(() => {

    resolve('foo');

  }, 300);

});

promise1.then((value) => {

  console.log(value);

  // expected output: "foo"

});

console.log(promise1);

// expected output: [object Promise]

上面的例子主要讲述了Promise的简单用法;


2.语法

new Promise( function(resolve, reject) {...} /* executor */  );

在使用Promise对象时需要对其进行实例化,并且将一个executor函数作为参数传入。这个函数有两个参数,分别名为resolve、reject的函数。当Promise函数实例化时会立即执行executor函数, resolve 和 reject 两个函数作为参数传递给executor。当resolve函数被调用时,promise的状态改为fulfilled(完成);当reject函数被调用时,promise的状态被改为rejected(失败)。在日常使用时executor函数中经常会有一些异步操作,例如:ajax请求、fetch API等;一旦异步操作执行完毕,可能成功/失败。要么调用resolve函数将promise状态改为fulfilled(完成)、要么调用reject函数将promise状态由rejected。如果失败状态不调用reject而是直接抛出错误,那么这个promise的状态也将是rejected。


3.原理分析

Promise 对象是一个代理对象(代理一个值),被代理的值在Promise对象创建时可能是未知的。它允许你为异步操作的成功和失败分别绑定相应的处理方法(handlers)。 这让异步方法可以像同步方法那样返回值,但并不是立即返回最终执行结果,而是一个能代表未来出现的结果的promise对象。

promise的几种状态

  • pending: 初始状态,既不是成功,也不是失败状态。
  • fulfilled:意味着成功状态
  • rejected:意味着失败状态

pending 状态的 Promise 对象可能会变为fulfilled 状态并传递一个值给相应的状态处理方法,也可能变为失败状态(rejected)并传递失败信息。当其中任一种情况出现时,Promise 对象的 then 方法绑定的处理方法(handlers )就会被调用。
注意知识点:Promise 对象的then方法包含两个参数:onfulfilled 和 onrejected,它们都是 Function 类型。当Promise状态为fulfilled时,调用 then 的 onfulfilled 方法,当Promise状态为rejected时,调用 then 的 onrejected 方法, 所以在异步操作的完成和绑定处理方法之间不存在竞争。原因:Promise.prototype.thenPromise.prototype.catch方法返回promise 对象, 所以它们可以被链式调用。如下图所示,图片来自MDN。

关于javascript Promise对象_第1张图片
promises.png

settled为Promise对象处在fulfilled或rejected状态。


3.方法

Promise.all(iterable)
输入:可迭代的对象(ArrayString等)
输出:新的Promise对象
描述:该方法iterable中所有promise都成功才会触发成功,一旦iterable中有一个失败,便会触发失败。当在触发成功状态以后,会把一个包含iterable里所有promise返回值的数组作为成功回调的返回值,顺序跟iterable的顺序保持一致。


Promise.race(iterable)
输入:可迭代的对象(ArrayString等)
输出:iterable中任意成功/失败的子promise
描述:iterable中任意一个子promise执行成功/失败,父promise马上也会用子promise的成功返回值或失败详情作为参数调用父promise绑定的相应句柄,并返回该promise对象。


Promise.resolve(value)
输入:一个值或者一个thenable(即,带有then方法的对象)
输出:一个状态由给定value决定的Promise对象
描述:如果value是thenable(即,带有then方法的对象),返回的Promise对象的最终状态由then方法执行决定;否则的话(value为空,基本类型或者不带then方法的对象),返回的Promise对象状态为fulfilled,并且将value传递给对应的then方法。通常而言,如果你不知道一个值是否是Promise对象,使用Promise.resolve(value) 来返回一个Promise对象,这样就能将value以Promise对象形式使用。


Promise.reject(reason)
输入:失败信息reason
输出:一个状态为失败的Promise对象
描述:将给定的reason失败信息传递给对应的处理方法


4.具体使用场景

function promiseAjax(url) {
  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();
  });
};

上述方法封装了一个对原生ajax返回promise的支持。
当使用时可直接这样调用

let httpUrl = "http://fetchData.com/getData"; 
promiseAjax(httpUrl).then(res=>{
  console.log(res);
})

js并没有线程等待一说,但对于其他服务端语言例如java有Thread.sleep(millis)可以阻塞当前线程;如果想要js也实现类似与java的效果可以这样写

function sleep(millis){
  return new Promise(resolve=>{
    setTimeout(resolve,millis);
  });
}

调用方式如下

sleep(1000).then(()=>{
/**TODO code block**/
});

下面这个例子是工作中经常使用的场景

var p1 = Promise.resolve(3);
var p2 = 1337;
var p3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'foo');
}); 

Promise.all([p1, p2, p3]).then(values => { 
  console.log(values); // [3, 1337, "foo"] 
});

将所有异步请求封装到Promise.all(iterable)中,使异步执行效率大大增加;同时返回值也将可以统一管理。


Promise.all 的快速返回失败行为

let p1 = new Promise((resolve, reject) => { 
  setTimeout(resolve, 1000, 'one'); 
}); 
let p2 = new Promise((resolve, reject) => { 
  setTimeout(resolve, 2000, 'two'); 
});
let p3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 3000, 'three');
});
let p4 = new Promise((resolve, reject) => {
  setTimeout(resolve, 4000, 'four');
});
let p5 = new Promise((resolve, reject) => {
  reject('reject');
});

Promise.all([p1, p2, p3, p4, p5]).then(values => { 
  console.log(values);
}, reason => {
  console.log(reason)
});

//From console:
//"reject"

//You can also use .catch
Promise.all([p1, p2, p3, p4, p5]).then(values => { 
  console.log(values);
}).catch(reason => { 
  console.log(reason)
});

//From console: 
//"reject"

Promise.all在任意一个传入的 promise 失败时返回失败。例如,如果你传入的 promise中,有四个 promise 在一定的时间之后调用成功函数,有一个立即调用失败函数,那么Promise.all将立即变为失败。上面例子中用到了两种捕获错误的方式,根据第3小结的原理解释,说明这两种方式是等效的。


Promise.all 当且仅当传入的可迭代对象为空时为同步:理解一下代码即可

var p = Promise.all([]); // will be immediately resolved
var p2 = Promise.all([1337, "hi"]); // non-promise values will be ignored, but the evaluation will be done asynchronously
console.log(p);
console.log(p2)
setTimeout(function(){
    console.log('the stack is now empty');
    console.log(p2);
});

// Promise { : "fulfilled", : Array[0] }
// Promise { : "pending" }
// the stack is now empty
// Promise { : "fulfilled", : Array[2] }

以上便是Promise的全部内容,关于更多关于Promise的知识可以访问

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

MDN开发人员值得信赖的官方教程,感谢MDN web docs对本教程的支持!

你可能感兴趣的:(关于javascript Promise对象)