ES6中的Promise对象小结

news/2024/7/11 1:07:20 标签: Promise, es6

es6提供原生的promise它比传统的解决方案回调函数和事件更加合理和强大">Promise是一种异步编程的解决方案,ES6提供原生的Promise,它比传统的解决方案,回调函数和事件,更加合理和强大。

Promise对象有以下两个特点:

1、对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending, resolved, rejected。只有异步操作的结果,可以决定是哪一种状态。

2、状态一旦改变,就不会再变化,并且任何时候都可以得到这个结果。

实用Promise对象,可以将异步操作用同步操作的流程表达出来,避免了层层嵌套的回调函数。

基本用法

var promise = new Promise(function(resolve, reject) {
  // ... some code

  if (/* 异步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});

注意,函数resolve, reject由JS引擎提供,不用自己部署。

resolve函数的作用是将Promise对象的状态从“未完成”变为“成功”(即从 Pending 变为 Resolved),在异步调用成功的时候使用,并将异步操作的结果作为参数传递出去;reject函数将Promise对象的状态从“未完成”变为“失败”(即从 Pending 变为 Rejected),在异步操作失败时调用,并将异步操作报出的错误作为参数传递出去。

promise.then(function(value) {
  // success
}, function(error) {
  // failure
});

Promise实例生成以后,可以用then方法分别指定Resolved状态和Rejected状态的回调函数。

一个完整的例子:

function timeout(ms) {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, ms, 'done');
  });
}

timeout(100).then((value) => {
  console.log(value);
});

timeout方法返回一个Promise实例。当Promise实例的状态变为Resolved,就会触发then方法绑定的回调函数。

另外,Promise对象在新建后就会立即执行。

下面是用Promise对象实现Ajax的例子:

var getJSON = function(url) {
  var promise = new Promise(function(resolve, reject){
    var client = new XMLHttpRequest();
    client.open("GET", url);
    client.onreadystatechange = handler;
    client.responseType = "json";
    client.setRequestHeader("Accept", "application/json");
    client.send();

    function handler() {
      if (this.readyState !== 4) {
        return;
      }
      if (this.status === 200) {
        resolve(this.response);
      } else {
        reject(new Error(this.statusText));
      }
    };
  });

  return promise;
};

getJSON("/posts.json").then(function(json) {
  console.log('Contents: ' + json);
}, function(error) {
  console.error('出错了', error);
});

Promise“嵌套”

如果调用resolve函数和reject函数时带有参数,那么它们的参数会被传递给回调函数。
reject函数的参数通常是Error对象的实例,表示抛出的错误;resolve函数的参数除了正常的值以外,还可能是另一个 Promise 实例:

var p1 = new Promise(function (resolve, reject) {
  // ...
});

var p2 = new Promise(function (resolve, reject) {
  // ...
  resolve(p1);
})

上面代码中,p1和p2都是 Promise 的实例,
但是,重要的来了,p2的resolve方法将p1作为参数,即一个异步操作的结果是返回另一个异步操作。

这时,p1的状态就会传递给p2,也就是说,p1的状态决定了p2的状态。如果p1的状态是Pending,那么p2的回调函数就会等待p1的状态改变;如果p1的状态已经是Resolved或者Rejected,那么p2的回调函数将会立刻执行。

注意,调用resolve或reject并不会终结 Promise 的参数函数的执行。

new Promise((resolve, reject) => {
  resolve(1);
  console.log(2);
}).then(r => {
  console.log(r);
});
// 2
// 1

Promise.prototype.then()

then方法的作用是为 Promise 实例添加状态改变时的回调函数。前面说过,then方法的第一个参数是Resolved状态的回调函数,第二个参数(可选)是Rejected状态的回调函数。

then方法可以链式调用。

getJSON("/post/1.json").then(function(post) {
  return getJSON(post.commentURL);
}).then(function funcA(comments) {
  console.log("Resolved: ", comments);
}, function funcB(err){
  console.log("Rejected: ", err);
});

上面代码中,第一个then方法指定的回调函数,返回的是另一个Promise对象。这时,第二个then方法指定的回调函数,就会等待这个新的Promise对象状态发生变化。如果变为Resolved,就调用funcA,如果状态变为Rejected,就调用funcB。

Promise.prototype.catch()

Promise.prototype.catch方法是.then(null, rejection)的别名,用于指定发生错误时的回调函数。

另外,then方法指定的回调函数,如果运行中抛出错误,也会被catch方法捕获。

Promise.resolve()

Promise.resolve()可以将现有对象转化为Promise对象。

等价于:

Promise.resolve('foo')
// 等价于
new Promise(resolve => resolve('foo'))

Promise.resolve方法的参数分成四种情况。

1、参数是一个Promise实例

如果参数是Promise实例,那么Promise.resolve将不做任何修改、原封不动地返回这个实例。

2、参数是一个thenable对象

thenable对象指的是具有then方法的对象,比如下面这个对象。

let thenable = {
  then: function(resolve, reject) {
    resolve(42);
  }
};

Promise.resolve方法会将这个对象转为Promise对象,然后就立即执行thenable对象的then方法。

3、参数不是具有then方法的对象,或根本就不是对象

如果参数是一个原始值,或者是一个不具有then方法的对象,则Promise.resolve方法返回一个新的Promise对象,状态为Resolved。

var p = Promise.resolve('Hello');

p.then(function (s){
  console.log(s)
});
// Hello

4、不带有任何参数

Promise.resolve方法允许调用时不带参数,直接返回一个Resolved状态的Promise对象。

所以,如果希望得到一个Promise对象,比较方便的方法就是直接调用Promise.resolve方法。

需要注意的是,立即resolve的Promise对象,是在本轮“事件循环”(event loop)的结束时,而不是在下一轮“事件循环”的开始时。

Promise.reject()

Promise.reject(reason)方法也会返回一个新的 Promise 实例,该实例的状态为rejected。

转载出处:http://blog.csdn.net/u014328357/article/details/76566855


http://www.niftyadmin.cn/n/1735297.html

相关文章

npm 报错:npm ERR! missing script: start npm ERR! A complete log of this run can be found in: npm ERR!

npm ERR! missing script: start npm ERR! A complete log of this run can be found in: npm ERR! C:\Users\Administrator\AppData\Roaming\npm-cache_logs\2017-11-20T09_43_06_459Z-debug.log npm run start 或者 npm run-script start需要在package.json的 scripts 中定义…

javascript中使用迭代操作数组替代for循环(map,filter,some,every,reduce,find )

1.Map map() 方法创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。 语法: let new_array arr.map(function callback(currentValue, index, array) { // Return element for new_array }[, thisArg]) 参数&#xff1…

React和Redux 之间的依赖注入connect(mapStateToProps、mapDispatchToProps)

在理解react-redux通过connect连接的关系之前,需要重温下组件的概念,组件分为两大类:展示组件和容器组件。展示组件就是用来显示UI的普通组件,不涉及业务逻辑和redux。容器组件的概念不容易理解,但它与展示组件之间却存…

理解JavaScript 执行机制及异步回调(setTimeout/setInterval/Promise)

对于javascript执行机制的理解一直都是混淆不清。在面试或工作的过程中,也经常会遇到代码执行顺序或函数生命周期加载等类似的问题,这些多多少少都与javascript的执行机制相关。今天发现一篇很好的文章,欣喜之余,加以转载&#xf…

为什么(什么时候)使用Redux?(三张图)

迷茫了,就回来看看!!! 1.为什么使用Redux? 2. Redux工作原理 3.什么时候使用Redux 使用场景: 组件需要根据状态发生显示变化state并不总是以单向的方式线性流动存在组件需要更新全局状态存在组件需要更新另…

XHR异步上传文件报错: “the request was rejected because no multipart boundary was found”

js 使用异步上传文件时报错: 解决方法: // 开始上传 xhr.open("POST", self.url, true); // xhr.setRequestHeader("Content-Type","multipart/form-data"); xhr.send(formData); 因为请求头的”Content-Type”会自动填充…

javascript实现异步上传图片

最近遇到图片上传的需求&#xff0c;由于第一次在移动端尝试写上传&#xff0c;还是小心为上&#xff0c;做了一个简单的demo&#xff0c;便于在此基础之上慢慢完善。 html代码&#xff1a; <form id"uploadForm" action"http://storage.test.com/file/upl…

深入JavaScript学习底层内容

最近有种感觉&#xff0c;愈发强烈&#xff01;随着代码量的积累叠加&#xff0c;接触到的前端新的东西越来越多&#xff0c;但是还是偶尔心存一种未知的不安定感或者危机感&#xff0c;这种感觉来自于对JavaScript未知部分的恐惧&#xff0c;来自于对解决问题却难以理解问题本…