Promise异步编程

一、什么是Promise

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。 所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。

从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。

以下是MDN对Promise的定义

The Promise object is used for asynchronous computations. A Promise represents a single asynchronous operation that hasn't completed yet, but is expected in the future.

译文:Promise对象用于异步操作,它表示一个尚未完成且预计在未来完成的异步操作。

二、同步和异步

 

我们知道,JavaScript的执行环境是「单线程」。

所谓单线程,是指JS引擎中负责解释和执行JavaScript代码的线程只有一个,也就是一次只能完成一项任务,这个任务执行完后才能执行下一个,它会「阻塞」其他任务。这个任务可称为主线程。

但实际上还有其他线程,如事件触发线程、ajax请求线程等。 这也就引发了同步和异步的问题。

同步:

while(true);

console.log("don't execute"); //不会执行

异步:

setTimeout(function() {

    console.log('taskA, asynchronous');

}, 0);

console.log('taskB, synchronize');

三、回调函数

 

回调函数是一段可执行的代码段,它以「参数」的形式传递给其他代码,在其合适的时间执行这段(回调函数)的代码。

var friends = ["Mike", "Stacy", "Andy", "Rick"];

friends.forEach(function (eachName, index){

    console.log(index + 1 + ". " + eachName); // 1. Mike, 2. Stacy, 3. Andy, 4. Rick

});

 

上面例子中的setTimeout就是一个回调函数

再看一次:

setTimeout(function() {

console.log('taskA, asynchronous');

}, 0);

console.log('taskB, synchronize');

四、为什么使用Promise

 

使用上面的回调函数的方式,如果回调函数嵌套很多层,很容易陷入回调地狱,代码可读性差

function fn(callback1, callback2) {

  // 耗时操作 let a = 0

  for (let i = 0; i < 100; i++) {

    a++

  }

  setTimeout(function() {

    callback1(++a)

    setTimeout(function() {

      callback2(++a)

    }, 0)

   }, 0)

}

function fn1(a) {

  console.log(a)

}

function fn2(a) {

  console.log(a)

}

fn(fn1, fn2)

五、Promise基本概念

 

Promise对象代表一个未完成、但预计将来会完成的操作。

ES6 规定,Promise对象是一个构造函数,用来生成Promise实例。

Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolvereject。它们是两个函数,由 JavaScript 引擎提供,不用自己部署。

resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;

reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

 

它有以下三种状态:

pending:初始值,不是fulfilled,也不是rejected

fulfilled:代表操作成功

rejected:代表操作失败

 

Promise有两种状态改变的方式,既可以从pending转变为fulfilled,也可以从pending转变为rejected

一旦状态改变,就「凝固」了,会一直保持这个状态,不会再发生变化。

当状态发生变化,promise.then绑定的函数就会被调用。

注意:Promise一旦新建就会「立即执行」,无法取消。

六、Promise基本用法

 

下面代码创造了一个Promise实例。

const promise = new Promise(

  // executor

  function(resolve, reject) {

    if (/* 异步操作成功 */){

      resolve(value);

    } else {

      reject(error);

    }

});

executor是带有 resolve 和 reject 两个参数的函数 。Promise构造函数执行时立即调用executor 函数, resolve 和 reject 两个函数作为参数传递给executor(executor 函数在Promise构造函数返回所建promise实例对象前被调用)。resolve 和 reject 函数被调用时,分别将promise的状态改为fulfilled(完成)或rejected(失败)。executor 内部通常会执行一些异步操作,一旦异步操作执行完毕(可能成功/失败),要么调用resolve函数来将promise状态改成fulfilled,要么调用reject 函数将promise的状态改为rejected。

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

promise.then(function(value) { // success }, function(error) { // failure }); then方法可以接受两个回调函数作为参数。第一个回调函数是Promise对象的状态变为resolved时调用,第二个回调函数是Promise对象的状态变为rejected时调用。其中,第二个函数是可选的,不一定要提供。这两个函数都接受Promise对象传出的值作为参数。

七、Promise实例应用

 

//简单的promise
const promise1 = new Promise(
  // executor
  function(resolve, reject) {
    if (false){
      resolve('request success');
    } else {
      reject('request error');
    }
});
promise.then(function(value) {
  console.log(value);
}, function(error) {
  console.log(error);
});

//then只传一个方法的情况
const promise2 = new Promise(
// executor
function(resolve, reject) {
if (false){
resolve('request success');
} else {
reject('request error');
}
});
promise2.then(function(value) {
console.log(value);
});
promise2.catch(function(error) {
console.log(error);
});

//链式调用
const promise3 = new Promise(
  // executor
  function(resolve, reject) {
    if (false){
      resolve('request success');
    } else {
    reject('request error');
    }
}).then(function(value) {
  console.log(value);
}).catch(function(error) {
  console.log(error);
});

//嵌套调用
const promise4 = new Promise(
  // executor
  function(resolve, reject) {
  if (true){
    resolve('request success');
  } else {
    reject('request error');
  }
}).then(function(value) {
  const nextPromise = new Promise(
    function(resolve, reject) {
      resolve('next request success');
   });
  return nextPromise;
}).then(function(value) {
  console.log(value);
}).catch(function(error){
  console.log(error);
});

 

posted @ 2019-05-13 10:28  Regina_wisdom  阅读(159)  评论(0编辑  收藏  举报