博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于Promise的详细总结
阅读量:6238 次
发布时间:2019-06-22

本文共 11123 字,大约阅读时间需要 37 分钟。

1. 异步回调

1.1 回调地狱

在需要多个操作的时候,会导致多个回调函数嵌套,导致代码不够直观,就是常说的回调地狱

1.2 并行结果

如果几个异步操作之间并没有前后顺序之分,但需要等多个异步操作都完成后才能执行后续的任务,无法实现并行节约时间

2. Promise

Promise本意是承诺,在程序中的意思就是承诺我过一段时间后会给你一个结果。 什么时候会用到过一段时间?答案是异步操作,异步是指可能比较长时间才有结果的才做,例如网络请求、读取本地文件等 

3. Promise的三种状态

  • Pending Promise对象实例创建时候的初始状态
  • Fulfilled 可以理解为成功的状态
  • Rejected 可以理解为失败的状态

then 方法就是用来指定Promise 对象的状态改变时确定执行的操作,resolve 时执行第一个函数(onFulfilled),reject 时执行第二个函数(onRejected)

4. 构造一个Promise

4.1 使用Promise

let promise = new Promise((resolve, reject) => {    setTimeout(() => {        if(Math.random()>0.5)            resolve('This is resolve!');        else            reject('This is reject!');    }, 1000);});promise.then(Fulfilled,Rejected)
  • 构造一个Promise实例需要给Promise构造函数传入一个函数。
  • 传入的函数需要有两个形参,两个形参都是function类型的参数。
    • 第一个形参运行后会让Promise实例处于resolve状态,所以我们一般给第一个形参命名为resolve,使 Promise 对象的状态改变成成功,同时传递一个参数用于后续成功后的操作
    • 第一个形参运行后会让Promise实例处于reject状态,所以我们一般给第一个形参命名为reject,将 Promise 对象的状态改变为失败,同时将错误的信息传递到后续错误处理的操作

4.2 es5模拟Promise

function Promise(fn) {    fn((data)=> {        this.success(data);    }, (error)=> {        this.error();    });}Promise.prototype.resolve = function (data) {    this.success(data);}Promise.prototype.reject = function (error) {    this.error(error);}Promise.prototype.then = function (success, error) {    this.success = success;    this.error = error;}

4.3 es6模拟Promise

class Promise {    constructor(fn) {        fn((data)=> {            this.success(data);        }, (error)=> {            this.error();        });    }    resolve(data) {        this.success(data);    }    reject(error) {        this.error(error);    }    then(success, error) {        this.success = success;        this.error = error;        console.log(this);    }}

 

5. promise 做为函数的返回值

function ajaxPromise (queryUrl) {  return new Promise((resolve, reject) => {    let xhr = new XMLHttpRequest();    xhr.open('GET', queryUrl, true);    xhr.send(null);    xhr.onreadystatechange = () => {      if (xhr.readyState === 4) {        if (xhr.status === 200) {          resolve(xhr.responseText);        } else {          reject(xhr.responseText);        }      }    }  });}ajaxPromise('http://www.baidu.com')  .then((value) => {    console.log(value);  })  .catch((err) => {    console.error(err);  });

6.promise的链式调用

  • 每次调用返回的都是一个新的Promise实例
  • 链式调用的参数通过返回值传递

then可以使用链式调用的写法原因在于,每一次执行该方法时总是会返回一个Promise对象

readFile('1.txt').then(function (data) {    console.log(data);    return data;}).then(function (data) {    console.log(data);    return readFile(data);}).then(function (data) {    console.log(data);}).catch(function(err){ console.log(err);});

7.promise API

7.1 Promise.all

  • 参数:接受一个数组,数组内都是Promise实例
  • 返回值:返回一个Promise实例,这个Promise实例的状态转移取决于参数的Promise实例的状态变化。当参数中所有的实例都处于resolve状态时,返回的Promise实例会变为resolve状态。如果参数中任意一个实例处于reject状态,返回的Promise实例变为reject状态。
    Promise.all([p1, p2]).then(function (result) {  console.log(result); // [ '2.txt', '2' ]});

    不管两个promise谁先完成,Promise.all 方法会按照数组里面的顺序将结果返回

7.2 Promise.race

  • 参数:接受一个数组,数组内都是Promise实例
  • 返回值:返回一个Promise实例,这个Promise实例的状态转移取决于参数的Promise实例的状态变化。当参数中任何一个实例处于resolve状态时,返回的Promise实例会变为resolve状态。如果参数中任意一个实例处于reject状态,返回的Promise实例变为reject状态。
    Promise.race([p1, p2]).then(function (result) {  console.log(result); // [ '2.txt', '2' ]});

    7.3 Promise.resolve

    返回一个Promise实例,这个实例处于resolve状态。

根据传入的参数不同有不同的功能:

  • 值(对象、数组、字符串等):作为resolve传递出去的值
  • Promise实例:原封不动返回

7.4 Promise.reject

返回一个Promise实例,这个实例处于reject状态。

  • 参数一般就是抛出的错误信息。

8. q

Q是一个在Javascript中实现promise的模块

8.1 q的基本用法

var Q = require('q');var fs = require('fs');function read(filename) {    var deferred = Q.defer();    fs.readFile(filename,'utf8', function (err, data) {        if(err){            deferred.reject(err);        }else{            deferred.resolve(data);        }    });    return deferred.promise;}read('1.txt1').then(function(data){    console.log(data);},function(error){    console.error(error);});

8.2 q的简单实现

module.exports = {    defer(){        var _success,_error;        return {            resolve(data){                _success(data);            },            reject(err){                _error(err);            },            promise:{                then(success,error){                    _success = success;                    _error = error;                }            }        }    }}

8.3 q的实现

var defer = function () {    var pending = [], value;    return {        resolve: function (_value) {            if (pending) {                value = _value;                for (var i = 0, ii = pending.length; i < ii; i++) {                    var callback = pending[i];                    callback(value);                }                pending = undefined;            }        },        promise: {            then: function (callback) {                if (pending) {                    pending.push(callback);                } else {                    callback(value);                }            }        }    };};

9. bluebird

实现 promise 标准的库是功能最全,速度最快的一个库

9.1 bluebird经典使用

var Promise = require('./bluebird');var readFile = Promise.promisify(require("fs").readFile);readFile("1.txt", "utf8").then(function(contents) {    console.log(contents);})var fs = Promise.promisifyAll(require("fs"));fs.readFileAsync("1.txt", "utf8").then(function (contents) {    console.log(contents);})

9.2 bluebird简单实现

module.exports = {    promisify(fn){        return function () {            var args = Array.from(arguments);            return new Promise(function (resolve, reject) {                fn.apply(null, args.concat(function (err) {                    if (err) {                        reject(err);                    } else {                        resolve(arguments[1])                    }                }));            })        }    },    promisifyAll(obj){        for(var attr in obj){            if(obj.hasOwnProperty(attr) && typeof obj[attr] =='function'){                obj[attr+'Async'] = this.promisify(obj[attr]);            }        }        return obj;    }}

10. 动画

    
move

11. co

11.1 co初体验

let fs = require('fs');function getNumber(){  return new Promise(function (resolve,reject) {    setTimeout(function(){      let number = Math.random();      if(number >.5){        resolve(number);      }else{        reject('数字太小');      }    },1000);  });}function *read(){  let a = yield getNumber();  console.log(a);  let b = yield 'b';  console.log(b);  let c = yield getNumber();  console.log(c);}function co(gen){  return new Promise(function(resolve,reject){    let g = gen();    function next(lastValue){      let {done,value} = g.next(lastValue);      if(done){         resolve(lastValue);      }else{        if(value instanceof Promise){          value.then(next,function(val){            reject(val);          });        }else{          next(value);        }      }    }    next();  });}co(read).then(function(data){  console.log(data);},function(reason){  console.log(reason);});

11.2 co连续读文件

let fs = require('fs');function readFile(filename){  return new Promise(function (resolve,reject) {    fs.readFile(filename,'utf8',function(err,data){      if(err)        reject(err);      else        resolve(data);    })  });}function *read(){  let a = yield readFile('./1.txt');  console.log(a);  let b = yield readFile('./2.txt');  console.log(b);}function co(gen){  let g = gen();  function next(val){    let {done,value} = g.next(val);    if(!done){      value.then(next);    }  }  next();}

12. Promise/A+完整实现

function Promise(executor) {  let self = this;  self.status = "pending";  self.value = undefined;  self.onResolvedCallbacks = [];  self.onRejectedCallbacks = [];  function resolve(value) {    if (value instanceof Promise) {      return value.then(resolve, reject)    }    setTimeout(function () { // 异步执行所有的回调函数      if (self.status == 'pending') {        self.value = value;        self.status = 'resolved';        self.onResolvedCallbacks.forEach(item => item(value));      }    });  }  function reject(value) {    setTimeout(function () {      if (self.status == 'pending') {        self.value = value;        self.status = 'rejected';        self.onRejectedCallbacks.forEach(item => item(value));      }    });  }  try {    executor(resolve, reject);  } catch (e) {    reject(e);  }}function resolvePromise(promise2, x, resolve, reject) {  if (promise2 === x) {    return reject(new TypeError('循环引用'));  }  let then, called;  if (x != null && ((typeof x == 'object' || typeof x == 'function'))) {    try {      then = x.then;      if (typeof then == 'function') {        then.call(x, function (y) {          if (called)return;          called = true;          resolvePromise(promise2, y, resolve, reject);        }, function (r) {          if (called)return;          called = true;          reject(r);        });      } else {        resolve(x);      }    } catch (e) {      if (called)return;      called = true;      reject(e);    }  } else {    resolve(x);  }}Promise.prototype.then = function (onFulfilled, onRejected) {  let self = this;  onFulfilled = typeof onFulfilled == 'function' ? onFulfilled : function (value) {    return value  };  onRejected = typeof onRejected == 'function' ? onRejected : function (value) {    throw value  };  let promise2;  if (self.status == 'resolved') {    promise2 = new Promise(function (resolve, reject) {      setTimeout(function () {        try {          let x = onFulfilled(self.value);          resolvePromise(promise2, x, resolve, reject);        } catch (e) {          reject(e);        }      });    });  }  if (self.status == 'rejected') {    promise2 = new Promise(function (resolve, reject) {      setTimeout(function () {        try {          let x = onRejected(self.value);          resolvePromise(promise2, x, resolve, reject);        } catch (e) {          reject(e);        }      });    });  }  if (self.status == 'pending') {    promise2 = new Promise(function (resolve, reject) {      self.onResolvedCallbacks.push(function (value) {        try {          let x = onFulfilled(value);          resolvePromise(promise2, x, resolve, reject);        } catch (e) {          reject(e);        }      });      self.onRejectedCallbacks.push(function (value) {        try {          let x = onRejected(value);          resolvePromise(promise2, x, resolve, reject);        } catch (e) {          reject(e);        }      });    });  }  return promise2;}Promise.prototype.catch = function (onRejected) {  return this.then(null, onRejected);}Promise.all = function (promises) {  return new Promise(function (resolve, reject) {    let result = [];    let count = 0;    for (let i = 0; i < promises.length; i++) {      promises[i].then(function (data) {        result[i] = data;        if (++count == promises.length) {          resolve(result);        }      }, function (err) {        reject(err);      });    }  });}Promise.deferred = Promise.defer = function () {  var defer = {};  defer.promise = new Promise(function (resolve, reject) {    defer.resolve = resolve;    defer.reject = reject;  })  return defer;}/** * npm i -g promises-aplus-tests * promises-aplus-tests Promise.js */try {  module.exports = Promise} catch (e) {}

13. 资源

转载于:https://www.cnblogs.com/Scar007/p/8536912.html

你可能感兴趣的文章
深入oracle 12c数据库备份与恢复(优化RMAN性能、Oracle flashback技术)
查看>>
【华为ACL】禁止某网段上网
查看>>
Linux启动的顺序说明
查看>>
5月15日
查看>>
DDoS***&防御[精品文章100篇]
查看>>
要学学好习一下mysql了
查看>>
linux 当路由器使用
查看>>
Exchange系列—配置传输规则
查看>>
1.3.1原文件声明规则
查看>>
Linux下搭建无人执守安装服务器
查看>>
第九节 三元操作符
查看>>
我的友情链接
查看>>
Win7新建Wifi热点(无工具版)
查看>>
IPPBX 2000 SIP 并发修改为一路
查看>>
修改Linux系统时间
查看>>
phalcon:使用路由和命名空间实现分组or模块化
查看>>
LVM Mirror Raid1管理
查看>>
last 命令:
查看>>
为linux安装epel-yum仓库
查看>>
自动登录TP-LINK路由器,获取所有信息,重启等等,实用方法
查看>>