ES6中Promise的使用方法实例总结

本文实例讲述了ES6中Promise的使用方法。分享给大家供大家参考,具体如下:

在javascript中,代码是单线程执行的,对于一些比较耗时的IO操作,都是通过异步回调函数来实现的。

但是这样会存在一个问题,当下一个的操作需要上一个操作的结果时,我们只能把代码嵌到上一个操作的回调函数里,这样一层嵌一层,最终形成回调地狱。

$.get('/login.php', function (login) {
  $.get('/user.php', function (user) {
    $.get('/info.php', function (info) {
      //代码就这样一层嵌一层,不够直观,维护也麻烦
    });
  });
});

为了解决这种问题,ES6中就提供了Promise方法来解决这种问题。

Promise是一个构造函数,通过它,我们可以创建一个Promise实例对象。

let p = new Promise(function (resolve, reject) {
  setTimeout(() => {
    console.log('OK');
    resolve('OK');
  }, 1000);
});

Promise构造函数接受一个函数作为参数,这个函数有两个参数,resolve和reject。

resolve函数是将Promise的状态设置为fulfilled(完成),reject函数是将Promise的状态设置为rejected(失败)。

上述代码,我们并没有进行任何调用,当运行时,间隔1秒后输出了'OK'。所以这里需要注意,我们通常使用Promise时,需要在外层再包裹一层函数。

let p = function () {
  return new Promise(function (resolve, reject) {
    setTimeout(() => {
      console.log('OK');
      resolve('OK');
    }, 1000);
  });
};
p();

上面的代码p();返回的是一个Promise实例对象,Promise对象上有 then() , catch() , finally() 方法。

then方法有两个参数,onFulfilled和onRejected,都是函数。

onFulfilled用于接收resolve方法传递过来的数据,onRejected用于接收reject方法传递过来的数据。

let p = function () {
  return new Promise(function (resolve, reject) {
    setTimeout(() => {
      if (Math.random() > 0.5) {
        resolve('OK');
      } else {
        reject('ERR');
      }
    }, 1000);
  });
};
p().then(function (data) {
  console.log('fulfilled', data);
}, function (err) {
  console.log('rejected', err);
});

then()方法总是会返回一个Promise实例,这样我们就可以一直调用then()。

在then方法中,你既可以return 一个具体的值 ,还可以return 一个Promise对象。

如果直接return的是一个数据,那then方法会返回一个新Promise对象,并以该数据进行resolve。

let p = function () {
  return new Promise(function (resolve, reject) {
    resolve(1);
  });
};
p().then(function (data) {
  console.log(`第 ${data} 次调用`);
  //注意这里直接返回的值
  //then会创建一个新的Promise对象,并且以返回的值进行resolve
  //那么该值会被下面的then方法的onFulfilled回调拿到
  return ++data;
}).then(function (data) {
  console.log(`第 ${data} 次调用`);
  return ++data;
}).then(function (data) {
  console.log(`第 ${data} 次调用`);
  return ++data;
});

如果返回的是一个Promise对象,请看下面代码。

let p = function () {
  return new Promise(function (resolve, reject) {
    resolve(1);
  });
};
p().then(function (data) {
  console.log(`第 ${data} 次调用`);
  return new Promise(function (resolve, reject) {
    resolve(++data);
  });
}).then(function (data) {
  console.log(`第 ${data} 次调用`);
  return new Promise(function (resolve, reject) {
    resolve(++data);
  });
}).then(function (data) {
  console.log(`第 ${data} 次调用`);
  return new Promise(function (resolve, reject) {
    resolve(++data);
  });
});

其实效果与直接返回值的是一样的。

即然then()可以进行链式操作,那我们最早之前的回调地狱写法,就可以通过它进行改进了。

function login() {
  return new Promise(function (resolve, reject) {
    $.get('/login.php', function (result) {
      resolve(result);
    });
  });
}
function user(data) {
  return new Promise(function (resolve, reject) {
    $.get('/user.php', function (result) {
      resolve(result);
    });
  });
}
function info(data) {
  return new Promise(function (resolve, reject) {
    $.get('/info.php', function (result) {
      resolve(result);
    });
  });
}
login().then(function (data) {
  console.log('处理login');
  //把login异步处理获取的数据,传入到下一个处理中。
  return user(data);
}).then(function (data) {
  console.log('处理user');
  //把user异步处理获取的数据,传入到下一个处理中。
  return info(data);
}).then(function (data) {
  console.log('处理info');
});

这样修改后,回调地狱层层嵌套的结构就变的清晰多了。上述代码是伪代码。

Promise对象还有一个catch方法,用于捕获错误,该方法与 then(null, onRejected) 等同,是一个语法糖。

let p = function () {
  return new Promise(function (resolve, reject) {
    resolve('开始');
  });
};
p().then(function (data) {
  console.log('1');
  return new Promise(function (resolve, reject) {
    reject('错误1');
  });
}).then(function (data) {
  console.log('2');
  return new Promise(function (resolve, reject) {
    reject('错误2');
  });
}).then(function (data) {
  console.log('3');
  return new Promise(function (resolve, reject) {
    reject('错误3');
  });
}).catch(function (reason) {
  console.log(reason);
});

注意,一旦操作中有错误发生,则会进入到catch中,后面的操作将不再执行。

Promise对象内部自带了try catch,当代码运行时错误,会自动以错误对象为值reject,并最终被catch捕获。

let p = function () {
  return new Promise(function (resolve, reject) {
    resolve('开始');
  });
};
p().then(function (data) {
  //注意这里打印了一个未定义的变量
  console.log(a);
}).catch(function (reason) {
  //这里会捕获到错误
  console.log('rejected');
  console.log(reason);
});

Promise还提供了,all(),race(),reject(),resolve()等在构造函数上的方法,调用这些方法并不需要实例化对象。

all()方法,可以让我们并行的执行异步操作,直到所有操作完成了,才执行回调。

function fn1() {
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      resolve('fn1');
    }, 1000);
  });
}
function fn2() {
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      resolve('fn2');
    }, 2000);
  });
}
function fn3() {
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      resolve('fn3');
    }, 3000);
  });
}
//all会等待所有操作完成,会把所有操作的结果放到一个数组中,传给then。
Promise.all([fn1(), fn2(), fn3()]).then(function (data) {
  console.log(data);
});

race()方法是谁先处理完,就以谁为准,把最先处理完的结果传给then。

function fn1() {
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      resolve('fn1');
    }, 1000);
  });
}
function fn2() {
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      resolve('fn2');
    }, 2000);
  });
}
function fn3() {
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      resolve('fn3');
    }, 3000);
  });
}
//race是以谁先处理完,就以谁为准,fn1最先处理完,那fn1的结果会传给then
//注意这里fn2和fn3还是会执行,不过不会进入then了
Promise.race([fn1(), fn2(), fn3()]).then(function (data) {
  console.log(data);
});

reject()方法,返回一个带有拒绝原因reason参数的Promise对象。

// Promise.reject('错误')
// 等同于
// new Promise(function(resolve, reject) {
//   reject('错误');
// });
let p = Promise.reject('错误');
p.then(function (data) {
}).catch(function (reason) {
  console.log(reason);
});

resolve()方法,根据传入的值返回一个Promise对象。

//如果传入的参数是普通值,则返回一个新Promise对象,并以该值resolve
let p1 = Promise.resolve('OK');
p1.then(function (data) {
  console.log(data);
});
//如果传入的参数是一个Promise对象,则原封不动的返回该Promise对象
let obj = new Promise(function (resolve, reject) {
  resolve('我是Promise对象');
});
let p2 = Promise.resolve(obj);
p2.then(function (data) {
  console.log(data);
  console.log(p2 === obj);
});
//如果传入的参数是一个thenable对象(带有then方法),
//会转换成Promise对象,并执行thenable对象的then方法
let then = {
  then(resolve, reject) {
    resolve('我是thenable对象');
  }
}
let p3 = Promise.resolve(then);
p3.then(function (data) {
  console.log(data);
});
//如果什么参数都不传入,则返回状态为resolved的Promise对象
let p4 = Promise.resolve();
p4.then(function (data) {
  console.log(data);
}).catch(function (reason) {
  console.log(reason);
});

感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.jb51.net/code/HtmlJsRun测试上述代码运行效果。

更多关于JavaScript相关内容可查看本站专题:《JavaScript操作DOM技巧总结》、《JavaScript页面元素操作技巧总结》、《JavaScript事件相关操作与技巧大全》、《JavaScript查找算法技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript错误与调试技巧总结》

希望本文所述对大家JavaScript程序设计有所帮助。

(0)

相关推荐

  • ES6 Promise对象概念与用法分析

    本文实例讲述了ES6 Promise对象概念与用法.分享给大家供大家参考,具体如下: 1.Promise概念 Promise 对象有三种状态: ① Fulfilled 可以理解为成功的状态 ② Rejected 可以理解为失败的状态 ③ Pending 既不是 Fulfilld 也不是 Rejected 的状态,可以理解为 Promise 对象实例创建时候的初始状态 2.三个重要方法 在 Promise 对象当中有三个重要方法----resolve, reject和then. resolve 方

  • ES6新特性六:promise对象实例详解

    本文实例讲述了ES6新特性之promise对象.分享给大家供大家参考,具体如下: 1. promise 介绍 它是一个对象,也就是说与其他JavaScript对象的用法,没有什么两样:其次,它起到代理作用(proxy),充当异步操作与回调函数之间的中介.它使得异步操作具备同步操作的接口,使得程序具备正常的同步运行的流程,回调函数不必再一层层嵌套. 它的思想是,每一个异步任务立刻返回一个Promise对象,由于是立刻返回,所以可以采用同步操作的流程.这个Promises对象有一个then方法,允许

  • 深入解析ES6中的promise

    ES6中的promise对象很早就听说过,据说是为了解决我们使用回调产生回调地狱的问题.今天下午既然有这么想学的欲望,就来看一看吧,当然参考的还是阮一峰老师的教程. 第一部分:什么是Promise 看本文的最后一个例子,迅速理解. Promise是ES6中的一个内置的对象(实际上是一个构造函数,通过这个构造函数我们可以创建一个Promise对象),它是为了解决异步问题的.Promise的英文意思是承诺. Promise的特点如下: •Promise有三种状态:Pending(进行中).Resol

  • 浅析Javascript ES6中的原生Promise

    前言 一个 Promise 对象可以理解为一次将要执行的操作(常常被用于异步操作),使用了 Promise 对象之后可以用一种链式调用的方式来组织代码,让代码更加直观.而且由于 Promise.all 这样的方法存在,可以让同时执行多个操作变得简单. Promise的兴起,是因为异步方法调用中,往往会出现回调函数一环扣一环的情况.这种情况导致了回调金字塔问题的出现.不仅代码写起来费劲又不美观,而且问题复杂的时候,阅读代码的人也难以理解. 举例如下: db.save(data, function(

  • 让你彻底掌握es6 Promise的八段代码

    前言 新的ES6中引入了promise的概念,目的是让回调更为优雅.层层嵌套的回调会让javascript失去美感和可读性,同时javascript也推荐采用链式的方式去书写函数调用.于是Promise就应运而生.本文将通过八段代码让大家彻底的掌握Promise,下面话不多说,来一起看看详细的介绍: 1.Promise的立即执行性 var p = new Promise(function(resolve, reject){ console.log("create a promise")

  • 深入理解ES6 Promise 扩展always方法

    ES6添加了Promise对象,成功时在then中处理,失败则在catch中处理,但有时候,我们需要在无论成功或失败时都要做一些事,比如隐藏loading, 记录日志等等,下面我们以浏览器端ajax请求为例,我们使用axios(它是基于Promise的): axios.get("/").then(()=>{ //处理逻辑 ... console.log("请求结束") hideLoading(); }).catch(()=>{ console.log(&

  • ES6中异步对象Promise用法详解

    本文实例讲述了ES6中异步对象Promise用法.分享给大家供大家参考,具体如下: 回忆一下ES5中的怎么使用异步方法 // es5中的异步回调 let ajax = function(callback){ console.log('执行') // 执行 setTimeout(() => { callback&&callback.call(); }, 1000) }; ajax(function(){ console.log('hello') // 1s后打印hello }); 使用

  • ES6中的Promise代码详解

    废话不多说了,直接给大家贴代码了,具体如下所示: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <script> var a=0 var test=function(resolve, reject){ setTimeou

  • ES6 Promise对象的含义和基本用法分析

    本文实例讲述了ES6 Promise对象的含义和基本用法.分享给大家供大家参考,具体如下: 1.Promise的含义 Promise是异步编程的一种解决方案,比传统的解决方案(回调函数和事件)更合理更强大. 所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件 (通常是一个异步操作)的结果.从语法上说,Promise是一个对象,从它可以获取异步操作的消息. Promise对象有以下2个特点: 1.对象的状态不受外界影响.Promise对象代表一个异步操作,有三种状态:Pend

  • ES6关于Promise的用法详解

    Node的产生,大大推动了Javascript这门语言在服务端的发展,使得前端人员可以以很低的门槛转向后端开发. 当然,这并不代表迸发成了全栈.全栈的技能很集中,绝不仅仅是前端会写一些HTML和一些交互,后台熟悉数据库的增删查改. 想必接触过Node的人都知道,Node是以异步(Async)回调著称的,其异步性提高了程序的执行效率,但同时也减少了程序的可读性.如果我们有几个异步操作,并且后一个操作需要前一个操作返回的数据才能执行,这样按照Node的一般执行规律,要实现有序的异步操作,通常是一层加

  • ES6 Promise对象的应用实例分析

    本文实例讲述了ES6 Promise对象的应用.分享给大家供大家参考,具体如下: The Promise object represents the eventual completion (or failure) of an asynchronous operation, and its resulting value. Promise 对象用于一个异步操作的最终完成(或失败)及其结果值的表示.简单点说,它就是用于处理异步操作的,异步处理成功了就执行成功的操作,异步处理失败了就捕获错误或者停止

  • 详解ES6 Promise对象then方法链式调用

    promise俗称链式调用,它是es6中最重要的特性之一 简单的说可以不停的then调用嵌套在调用(异步之后,链式调用方式执行回调),这种操作方式称为promise then()方法的作用是Promise实例添加解决(fulfillment)和拒绝(rejection)状态的回调函数.then()方法会返回一个新的Promise实例,所以then()方法后面可以继续跟另一个then()方法进行链式调用. let p = new Promise((resolve, reject) => { set

随机推荐