JavaScript Promise 记录

link:学习资料来源

  1. http://es6.ruanyifeng.com/#docs/promise
  2. https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Promise/resolve

1. Promise 基本介绍

  • Promise 是JS 用来处理异步编程的一种方法, 这个方法比传统的回调函数 (callback function) 在使用上更合理更强大. ES 将这个写入标准中, 统一了用法.
  • Promise 可以理解为一个容器, 容器里放的是需要等待才会完成的事件, Promise 要做的就是告诉我们当前这个事件处理的状态.
  • Promise 两个特点:
    1. Promise 对其中处理的事件有三个状态, 分别是 Pending 进行中, fulfilled 完成, rejected 失败. 外部操作无法改变这其中的状态.

    2. Promise 的状态改变有两种可能: 从 pending 到 fulfilled, 从 pending 到 rejected. 一旦状态发生改变, 就凝固了, 不会再出现变化,这种状态称为 resolved. 使用者可以任何时候得到这个结果.

  • Promise 的缺点:
    1. 中途无法停止 Promise
    2. 无法得到 Pending 的具体状态
    3. 如果不在 Promise 中使用 callback 就错误无法反应到外部.
  • 2. 一个简单的 Promise 范例

console.log("JS Promise")

const promise1 = new Promise(function(resolved,reject){
	console.log("Promise block")
    setTimeout(resolved("welcome aiden"), 100, 'done');
})

// promise.then(resolved_function, reject_function)
promise1.then(function(value){
    console.log(value)
},function(error){
    console.log("error")
})
// 当然你也可以直接这样写.
// Promise.resolve()将在后面说明.
const promise2 = Promise.resolve("welcome aiden")
promise2.then(value => console.log(value))

上面这段代码没什么实际意义 ?.简单来看一些这段代码. 最开始先新建一个 Promise 实例,接受一个匿名函数,匿名函数中包括两个 function ,分别对应的是 resolved和 reject.之后通过 promise.then( resolved_function, reject_function) 将 resolved 和 reject callback 描述完整.下面附上一段实现 Ajax 操作的例子.
const getJSON = function(url) {
  const promise = new Promise(function(resolve, reject){
    const handler = function() {
      if (this.readyState !== 4) {
        return;
      }
      if (this.status === 200) {
        resolve(this.response);
      } else {
        reject(new Error(this.statusText));
      }
    };
    const client = new XMLHttpRequest();
    client.open("GET", url);
    client.onreadystatechange = handler;
    client.responseType = "json";
    client.setRequestHeader("Accept", "application/json");
    client.send();

  });

  return promise;
};

getJSON("/posts.json").then(function(json) {
  console.log('Contents: ' + json);
}, function(error) {
  console.error('出错了', error);
});
上述代码中,resolved 和 reject 都含有参数,参数会传递到 callback function 中.甚至我们可以再次传递一个新的 Promise.
const p1 = new Promise(function (resolve, reject) {
    resolve("hello world p1&p2")
    console.log("我先来")
})

const p2 = new Promise(function (resolve, reject) {
    resolve(p1)
})
p2.then( value => console.log(value) )
console.log( "p1 === p2 ?", p1 === p2 )

const p3 = Promise.resolve("hello world p3&p4")
const p4 = Promise.resolve(p3)
console.log("p3 === p4 ?", p3 === p4)

const p5 = Promise.resolve("hello world p5&p6")
const p6 = Promise.resolve(p5).then( value => console.log(value) )
console.log("p5 === p6 ?", p5 === p6)
//output
// 我先来
// p1 === p2 ? false
// p3 === p4 ? true
// p5 === p6 ? false
// hello world p5&p6
// hello world p1&p2
这里有一些重要的内容需要了解, 首先我们要先知道, Promise 在 resolved 后得到的是一个具有特定内容物的 Promise 容器(我是这么理解的?). 并且实际使用上, Promise 并不会因为 resoleve 了就结束这个 block 内的内容,还是会继续执行下去.并且要知道, resolve 是在本轮事件的最后才会执行.当时如果是加上 return resolve 就不会继续执行后续的内容了.
在前面的代码中我们可以看到 p2 的 resolve 中传递的是 p1, 最终结果输出是 Promise p1 中 resolved value. 原因是在 Promise.resolve(item) 中,文章后续会提到.
在前面范例中 code 中出现 p1 === p2 为 false 的原因可能只是因为 p1, p2 的写法比 p3, p4 而言, p4多了一个执行 function 的动作, 因此还没有执行完毕.

3. Promise.prototype.then()

then 是定义在 Promise.prototype 上的方法,作用是为 Promise 添加一个状态改变时的 callback function,允许两个 function 当参数,第一个是 resolve function,第二个是 reject function. then 的方法是返回一个新的 Promise 实例,因此可以在 then 的后面继续接 then.
const sum = new Promise((resolve,reject) => {
    resolve(10)
})
sum.then((value) => {
    return (10+value)
}).then((value) =>{
    console.log(value)
})

4. Promise.prototype.catch()

catch()是用来处理 Promise 的错误信息.并且 catch 会同时监听 Promise 中的 reject 信息以及 resolve function 中的错误信息. 这是因为在 Promise 中错误是会持续传递的,直到被 catch 到.在优先级上如果先定义了 “.then” reject function, 错误信息会先被 reject function 处理. 并且如果 Promise 已经 resolve 那么就不在继续处理后续的 throw error.
推荐使用上是不在 then 中定义 reject function, 一致使用 catch 处理错误.
// test file
const p1 = new Promise((resolve, reject) => {
    resolve("Promise resolve")
    //throw new Error('Promise Error')
})
p1.then(
    value => console.log(new Error('Resolve Error')),
    // error => console.log("reject: ", error)
).catch(
    error => console.log("catch: ", error)
)
//output
//Error: Resolve Error
如果在 Promise 中没有定义 catch(), 那么错误并不会传到外部.
// Promise 中的错误并不会影响外部代码
const p2 = new Promise((resolve, reject) => {
    resolve(x+2)
})
p2.then(
    value => console.log(value)
).catch(
    error => console.log(error)
)
setTimeout( () => console.log(1+2), 2000)
// output
// ReferenceError: x is not defined
// 3

5. Promise.prototype.finally()

finally() 是 ES2018 引入的.目的是不管 Promise 状态如何,都会执行的操作.同时 finally() 并不接受任何参数,意味着就是 finally 是不管先前 Promise 的结果为何,都会执行的部分,并不会依赖 Promise 的结果.
promise
.then(result => ···)
.catch(error => ···)
.finally(() => ···);

6. Promise.all()

Promise.all() 将多个 Promise 实例包装成一个新的实例.在结果的处理上,只有被包装进来的所有的 Promise 实例都是 fulfilled 的时候, all 的结果才会是 fulfilled, 不然的话就会处理第一个被 reject 的 Promise.
// Promise.all() 范例
const promises = [2, 3, 5, 7, 11, 13].map(function (id) {
  return getJSON('/post/' + id + ".json");
});

Promise.all(promises).then(function (posts) {
  // ...
}).catch(function(reason){
  // ...
});
如果包装进来的 Promise 自己定义了 catch,那么发生错误的时候就不会进入 Promise.all() 的 catch().原因是 Promise 在 catch 之后回传的还是一个 Promise,并且原先的 Promise 已经被指代成 catch 后的结果,对 Promise.all 而言就全被变成了 fulfilled, 因此不会执行 Promise.all.catch

7. Promise.race()

跟 Promise.all() 一样是将多个 Promise 包装起来,不同点在于,Promise.all() 是所有打包的内容状态发生变化后处理. Promise.rice() 则是处理第一个状态发生变化的 Promise()

8. Promise.resolve()

这个方法是将现有对象转换成 Promise 对象,对象可以是以下四种情况.
1. 一个 Promise()
2. 一个 thenable对象
3. 不是对象的参数,或者是不具有 then 的对象
4. 不带任何参数
1. 参数是一个 Promise 的时候,会直接回传这个 Promise().这里也就解释了前面为什么直接判断 p1 === p2.
2. thenable 指的是具有 then 属性的对象. Promise.resolve() 会把这个对象直接转成一个 Promise 对象.并且直接执行其中的 then .
const thenable = {
	then: (resolve, reject) => {
		resolve(42)
	}
}
const p = Promise.resolve(thenable).then(
    value => console.log(value)
)
// 42
事实上在处理 thenable 的时候,会尝试解开这个 thenable 直到取得一个不是 Promise 的具体的值为止.这
3. 如果参数是一个不具有 then 方法或者不是对象的内容.Promise.resolve() 会将状态直接变成 resolve 并执行相对的 call back function, 同时会将参数传递.
4. 如果只是希望得到一个 Promise 对象,使用 Promise.resolve 可以直接调用.直接得到一个 resolved 状态的 Promise 对象.
setTimeout(function () {
  console.log('three');
}, 0);
Promise.resolve().then(function () {
  console.log('two');
});
console.log('one');
// one
// two
// three
须要注意的是,即使是直接得到的 resolved 对象,还是需要等到当前事件循环结束才会执行.

9. Promise.reject()

Promise.reject() 是可以快速得到一个状态为 rejected 的 Promise 对象.跟 Promise.resolve() 不同的地方在于.Promise.reject() 接收的参数会原封不动的传递下去.
const thenable = {
  then(resolve, reject) {
    reject('出错了');
  }
};
Promise.reject(thenable)
.catch(e => {
  console.log(e === thenable)
})
// true
从上面的结果可以看出,Promise.reject 直接将 thenable 传递给了 catch 并不是只是获得"出错了"这个字串.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值