资讯专栏INFORMATION COLUMN

ES6之Promise学习

MrZONT / 1229人阅读

摘要:初识对象是一个构造函数,其接受一个函数作为参数,为这个函数的参数,函数内部一般为异步执行的代码,作为异步执行完成之后成功的回调,作为异步执行抛错的回调。构造函数可以理解为执行异步的过程,其和为执行异步调用结果的回调函数。

初识Promise

Promise对象是一个构造函数,其接受一个函数作为参数,resolvereject为这个函数的参数,函数内部一般为异步执行的代码,resolve作为异步执行完成之后成功的回调,reject作为异步执行抛错的回调。Promise构造函数可以理解为执行异步的过程,其resolvereject为执行异步调用结果的回调函数。

// 代码1
var p = new Promise((resolve, reject) => {
  // 执行一系列的异步执行
  // some codes...
  if (true) {
    resolve("异步执行成功");
  } else {
    reject("异步执行抛错");
  }
}); // fulfilled: 异步执行成功 ; 非fulfilled: 异步执行抛错
Promise的异步处理 then和catch的使用

Promise构造函数返回一个异步执行之后的promise对象,该对象对异步的结果进一步处理。

// 代码2
p
  .then((res) => {
    // try catch 手动抛错
    try {
      // console.log("异步返回成功状态");
      throw Error("错误代码");
    } catch(e) {
      console.log("执行catch");
      return Promise.reject(e);
    }
  })
  .catch((res) => {
    console.log(res); // 输出上一个 then 中 catch 的 e
    return "这里由错误信息过去的数据";
  })
  .then((res) => {
    console.log(res); // 若上一个catch执行,输出:这里由错误信息过去的数据
  })

以上代码执行结果:

# 结果1
执行catch
Error: 错误代码
    at p.then (**/promise.js:77:10)
    at process._tickCallback (internal/process/next_tick.js:109:7)
    at Module.runMain (module.js:607:11)
    at run (bootstrap_node.js:423:7)
    at startup (bootstrap_node.js:147:9)
    at bootstrap_node.js:538:3
这里由错误信息过去的数据
promise对象的链式调用

代码2可以看出,promise对象状态为resolve的时候,执行then方法,而且在不抛错情况下会持续执行链式调用的then方法,若then方法抛出异常或者抛出返回Promise.reject()方法,会转到执行catch方法,若catch方法返回的不是Promise.reject()方法或者不抛出异常,则所有使用return返回的数据都会作为参数传给下一个then函数参数的参数,即代码2中的最后一个then方法指定函数参数的res是上一个catchreturn的数据。

var p = new Promise((resolve, reject) => {
  resolve("ok");
});
p.then((msg) => {
  console.log(msg);
  return Promise.reject("then01抛错");
}).catch((errMsg) => {
  console.warn(errMsg);
}).then(() => {
  console.log("then02再执行");
}).then(() => {
  console.log("then03再执行");
  return Promise.reject("then03抛错");
}).catch((errMsg) => {
  console.warn(errMsg);
  return "catch02 return 给下一个then指定方法的值";
}).then((msg) => {
  console.log(msg);
});

运行结果如下:

这是因为then方法和catch方法返回的都是一个promise对象。then方法指定的回调函数抛出错误会被下一个catch方法捕获,多个then方法执行也是如此。catch方法会捕获上一个catch方法(如果有的话)之后抛错的错误。

换言之,无论是then方法还是catch方法,返回的都是一个promise对象,其状态取决于上一个方法指定的函数是否顺利执行或者没有返回Promise.reject()

Promise状态

一旦Promise的状态变为resolved或者rejected,就会永久保持该状态,不会再变。

var p = new Promise((resolve, reject) => {
  resolve("ok");
  throw new Error("wrong");
});
p.then((msg) => {
  console.log(msg);
}).catch((errMsg) => {
  console.warn(errMsg);
});

// ok

在Promise的参数函数中,由于先断定了resolved状态,所以在之后只会执行then函数,后面抛出的错误会等于没抛出来。

另外,“事件循环”会对抛出的结果有影响。

var p = new Promise((resolve, reject) => {
  resolve("ok");
  setTimeout(() => {
    throw new Error("wrong");
  }, 0);
});
p.then((msg) => {
  console.log(msg);
}).catch((errMsg) => {
  console.warn(errMsg);
});

// ok

// 浏览器抛出的错误
// index.js:4 Uncaught Error: wrong
//    at setTimeout (index.js:4)
// setTimeout    @    index.js:4

在本轮“事件循环”中,promise对象p先执行,所以构造函数Promise的指定函数先输出‘ok’;在进入到下一次的“事件循环”的时候,由于Promise函数体已经执行完毕,故后面抛出的错误是在Promise函数体外抛出的,Promise函数体无法捕获到这个错误。

Promise.resolve()

Promise.resolve()接受一个参数,其返回一个promise对象的状态会因为传入的参数的不同而不同。

参数分别以下几种情况:

返回一个状态为resolved的promise对象,也就是下一步会执行then方法。

var p = Promise.resolve();

p.then((res) => {
  console.log("then");
}).catch((res) => {
  console.log("catch");
});

// then

thenable对象

var thenable = {
  then: function (resolve, reject) {
    console.log("立即执行thenable的then的方法" + Date.now());
    resolve("断定之后的信息");
  }
}

var p = Promise.resolve(thenable);

p.then((res) => {
  console.log(res);
});

// 立即执行thenable的then的方法1494485393447
// 断定之后的信息

// 相当于

var p = new Promise(function (resolve, reject) {
  console.log("立即执行thenable的then的方法" + Date.now());
  resolve("断定之后的信息");
});

p.then((res) => {
  console.log(res);
});

// 立即执行thenable的then的方法1494485454503
// 断定之后的信息

thenable对象作为参数,在执行Promise.resolve(thenable)方法的时候,会立即执行thenable对象中的then方法,并且其返回的Promise对象的状态取决于thenable对象的then方法执行的是resolve()还是reject()。这种情况下,就相当于Promise构造函数以thenable对象的then方法作为参数,实例化一个Promise实例。

一个非Promise对象,且不含有then方法的对象------非thenable对象

var p = Promise.resolve({
  a: 1
});
p.then((res) => {
  console.log(res);
});

// { a: 1 }

var p01 = Promise.resolve("Hello Promise!");
p01.then((res) => {
  console.log(res);
});

// Hello Promise!

这种情况下,Promise.resolve()的状态为resolved,其接收的参数会作为then方法指定函数的参数。

Promise对象

var p01 = new Promise((resolve, reject) => {
  reject("Throw some error! Come on! You bite me.");
});

var p = Promise.resolve(p01);

p.then((res) => {
  console.log("这是then方法");
}).catch((errMsg) => {
  console.log(errMsg);
});

// Throw some error! Come on! You bite me.

传入的是一个Promise对象,Promise.resolve()返回的对象的状态就是传入的Promise对象的状态。

Promise.reject()

Promise.reject(reason)方法同样返回一个状态为rejectedPromise对象实例。值得注意的是,参数reason(Promise状态rejected的原因)不论是什么值,都会传给返回的Promise对象的catch方法指定的函数作为参数。

var p = Promise.reject("Throw some error! Come on! You bite me.");

p.then((res) => {
  console.log("这是then方法");
}).catch((errMsg) => {
  console.log(errMsg);
});

// Throw some error! Come on! You bite me.
promise对象的使用场景——图片加载
var imgPromise = function (url) {
  return new Promise((resolve, reject) => {
    var img = new Image();
    img.src = url;
    img.onload = resolve;
    img.onerror = reject;
  });
}
imgPromise("http://imgurl")
  .then((res) => {
    console.log("图片加载完成");
  })
  .catch((res) => {
    console.log("图片加载失败");
  }):

参考文章

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/82808.html

相关文章

  • ES6学习笔记Promise

    摘要:上代码异步执行成功的构造函数接收一个函数参数,并传入两个参数,分别表示异步操作执行成功后的回调函数和异步操作执行失败后的回调函数。第一个回调函数是对象的状态变为时调用,第二个回调函数是对象的状态变为时调用。 这篇文章只解决三个问题。什么是promise? promise有什么用?promise怎么用? 1.什么是promise? 对于ES6来说,就是一个构造函数,可以用new Prom...

    zoomdong 评论0 收藏0
  • JS笔记

    摘要:从最开始的到封装后的都在试图解决异步编程过程中的问题。为了让编程更美好,我们就需要引入来降低异步编程的复杂性。异步编程入门的全称是前端经典面试题从输入到页面加载发生了什么这是一篇开发的科普类文章,涉及到优化等多个方面。 TypeScript 入门教程 从 JavaScript 程序员的角度总结思考,循序渐进的理解 TypeScript。 网络基础知识之 HTTP 协议 详细介绍 HTT...

    rottengeek 评论0 收藏0
  • ES6-7

    摘要:的翻译文档由的维护很多人说,阮老师已经有一本关于的书了入门,觉得看看这本书就足够了。前端的异步解决方案之和异步编程模式在前端开发过程中,显得越来越重要。为了让编程更美好,我们就需要引入来降低异步编程的复杂性。 JavaScript Promise 迷你书(中文版) 超详细介绍promise的gitbook,看完再不会promise...... 本书的目的是以目前还在制定中的ECMASc...

    mudiyouyou 评论0 收藏0
  • ES6 异步编程二:Promise

    摘要:今天对于处理异步调用已经有了很多成熟的方案,在我看来这些方案都无外乎在解决一个问题如何能看似顺序地传递异步调用的结果,本文要说的就是原生提供的一个解决方案。在对进行叙述之前,依旧引用阮大的入门一书中的章节便于大家更严谨和全面的学习和参考。 异步回调的泥潭 异步回调是最直接的异步结果处理模式,将一个回调函数callback扔进异步处理函数中,当异步处理获得结果之后再调用这个回调函数就可以...

    Gilbertat 评论0 收藏0
  • Promise源码学习(2)

    摘要:源码学习本篇为上一篇源码学习的补充,主要是来介绍和方法。那个率先改变的实例的返回值,就传递给的回调函数。基本介绍可见阮一峰老师的书籍。的状态由决定,分成两种情况。只有的状态都变成,的状态才会变成,此时的返回值组成一个数组,传递给的回调函数。 Promise源码学习(2) 本篇为上一篇源码学习(1)的补充,主要是来介绍Promise.all()和Promise.race()方法。闲话少叙...

    cfanr 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<