博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Promise实现
阅读量:6080 次
发布时间:2019-06-20

本文共 11134 字,大约阅读时间需要 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) {}复制代码

转载地址:http://wrhgx.baihongyu.com/

你可能感兴趣的文章
Windows Server 2008 计划任务配置(任务计划程序)每分钟执行BAT
查看>>
【VNC】Linux环境VNC服务安装、配置与使用
查看>>
动态创建地图文档MXD并发布地图服务
查看>>
Repodata is over 2 weeks old. Install yum-cron? Or run: yum makecache fast
查看>>
单例模式讲解
查看>>
Linux权限管理(笔记)
查看>>
(笔记)电路设计(二)之串联匹配电阻的应用
查看>>
Linux下的grep搜索命令详解(二)
查看>>
C 基本语法
查看>>
Codeforces Round #258 (Div. 2) A. Game With Sticks 水题
查看>>
Server 2008 R2 事件查看器实现日志分析
查看>>
解决Cookie乱码问题
查看>>
javascript中的链表结构—从链表中删除元素
查看>>
用实例揭示notify()和notifyAll()的本质区别
查看>>
Android MediaPlayer接口及状态迁移
查看>>
JQuery------prevAll(),nextAll(),attr()方法的使用
查看>>
Disciz!NT开源资源汇总
查看>>
Python网络编程笔记
查看>>
Vim自动补全神器–YouCompleteMe
查看>>
Mysql 小工具
查看>>