普罗米修斯 Promise

盗火的普罗米修斯

  曾经我在哪本书上看过这样的介绍,Promise 的英文是从希腊语的直译Prometheus演变过来,Promise也就是表明着先知 将来的意思。在希腊神话中,是最具智慧的神明之一,最先的泰坦巨神后代,名字有“先见之明”(Forethought)的意思。泰坦十二神伊阿佩托斯与名望女神克吕墨涅的儿子。普罗米修斯不只创造了人类,给人类盗来了火,还教会了他们许多知识和技能。 后来因为给人类带来了火种,他吩咐火神给普罗米修斯最严厉的惩罚。天天还要派一直鹰去啄他的肝脏,夜晚的时候肝脏又会从新长出来,夜以继日的承受折磨。


故事结束,开始吹牛X

异步函数 Promise

  我我的以为Promise 函数跟 普罗米修斯很像,都是表明着处理将来的事情的先知。既然能处理将来的事情,那就表明着它拥有很是的能力,听我慢慢吹来呀~ 首先来看看官方的吹牛文档解释:ajax

所谓Promise,简单说就是一个容器,里面保存着某个将来才会结束的事件(一般是一个异步操做)的结果。从语法上说,Promise 是一个对象,从它能够获取异步操做的消息。Promise 提供统一的 API,各类异步操做均可以用一样的方法进行处理。json

你看没错吧,是否是很像一个先知能够处理将来的事情?既然是神仙确定是我们凡人管不了的,为啥管不了那?就体如今它三个内部状态上:api

对象的状态不受外界影响。Promise对象表明一个异步操做,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)只有异步操做的结果,能够决定当前是哪种状态,任何其余操做都没法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其余手段没法改变。数组

看见了吗,敲黑板划重点,神仙已经决定的东西就不能改变。并且一旦new Promise对象就不能取消,讲究~promise

那如何使用那?下面来看一个简单的例子:bash

const promise = new Promise (function(resolve, reject) { //这是先知啊,先知
  if (/* 异步操做成功 */){
    resolve(value);  // resolve就是这事儿先知赞成了,你就干就完了
  } else {
    reject(error);  // reject就是这事儿先知不一样意,白b扯了
  }
});
复制代码

注意上面的事情其实有没有发生?没有,先知嘛预知将来的事情,何时发生那?固然先知赞成的时候也就是说状态变成resolved。只要一resolved 立刻就能够then了,划重点 敲黑板 then 就是这玩意。app

promise.then(function(value) {
  // 妥妥的这个已经办了,下面你想咋地吧?能够连式操做无限then下去
}, function(error) {
  // 失败了消停的把错误信息打出来把
  console.log("错误信息:"+error)
});
复制代码

那么坑人的玩意来了,请看下面代码,谁先打印?异步

let promise = new Promise(function(resolve, reject) {
  console.log('Promise');
  resolve();
});

promise.then(function() {
  console.log('resolved.');
});

console.log('Hi!');
复制代码

上面代码中,Promise 新建后当即执行,因此首先输出的是Promise。而后,then方法指定的回调函数,将在当前脚本全部同步任务执行完才会执行,因此resolved最后输出。那么接下来这段 函数

你要是能直接写出答案,基本Promise就不用看了,根据上面的理论,Promise一旦创建立刻就执行,可是我们说了 resolve 是将来的状态,因此第二行代码先等一等,三行代码也不用看了,确定是四行代码先执行,而后往下走 第六行执行,回过头来 第三行直接成功了,因此会接下去执行,最后一个不用我说了吧,第二行代码须要走个完成的resolve状态,把1传递给第五行的t参数,因此确定是最后执行的。


概念吹完了,来看势力post

妥了,接下来看一个用Promise对象实现的 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);
});
复制代码

是否是很简单,一点都不难,只是把ajax的操做流程放到了先知的内部,让先知帮你获取各类成功失败的状态!结合实际,咱们在工做中可能一次要请求好几个接口的数据,Promise提供了一个更加简单的方法

const p = Promise.all([p1, p2, p3]);
复制代码

很好理解,all 的参数表明这一个可执行的任务队列,只要里面有任务就能够往下执行,也就是我们访问的多个api集合组成的数组。

// 生成一个Promise对象的数组
const promises = [2, 3, 5, 7, 11, 13].map(function (id) {
  return getJSON('/post/' + id + ".json"); //ID 做为参数 变成动态请求
});

Promise.all(promises).then(function (posts) {
  // ...
}).catch(function(reason){
  // ...
});
复制代码

还有一个相似 all的api Promise.race,Promise.race方法的参数与Promise.all方法同样,若是不是 Promise 实例,就会先调用下面讲到的Promise.resolve方法,将参数转为 Promise 实例,再进一步处理

const p = Promise.race([
  fetch('/resource-that-may-take-a-while'),
  new Promise(function (resolve, reject) {
    setTimeout(() => reject(new Error('request timeout')), 5000)
  })
]);

p
.then(console.log)
.catch(console.error);
复制代码

上面代码中,若是 5 秒以内fetch方法没法返回结果,变量p的状态就会变为rejected,从而触发catch方法指定的回调函数。

妥妥滴,既然到这里我估计你应该懂了,其实任何技术都不难,都能拆分红若干个简单点。任意简单的点组合起来就又复杂了,正所谓大道至简,相信万事万物都是简单的原理,怀着敬畏的心理去学习,终究会获得本身的收获。

相关文章
相关标签/搜索