博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
学习promise编写和使用
阅读量:6829 次
发布时间:2019-06-26

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

promise实现

Promise是Javascript中的一种异步编程实现方式,js中异步编程主要是指浏览器DOM事件处理,setTimeout/setInterval,ajax等,通过传入回调函数来实现控制反转。Promsie对象符合CommonJS编程规范,目的是为异步编程提供统一接口,它最大的优点就是避免了回调金字塔。

假设要实现一个用户展示的任务,任务分为三步:

  1. 获取用户信息

  2. 获取用户图片

  3. 弹窗提示

    一般之前使用方式为:

之前已经对getUserInfo()getUserImage(),showTip()方法进行了定义

getUserInfo(id, function(info){    getUserImage(info.img, function(){        showTip();    })})

如果回调函数不止3个,那将会是一个非常长的回调,换成Promise实现:

//getUserInfo返回promisegetUserInfo(id)    .then(getUserImage)    .then(showTip)    .catch(function(e){        console.log(e);    });

简单的讲,Promsie的思想就是每一个异步任务返回一个promise对象,该对象有一个then方法,允许指定回调函数。这里getUserInfo的回调函数就是getUserImage

getUserInfo函数要进行如下改写(这里用jQuery的Deferred()实现)

function getUserInfo(id){    var dfd = $.Deferred();    setTimeout(function(){        //获取用户信息        dfd.resolve();    }, 500);    return dfd.promise;}

这样一种写法回调函数就成了链式写法,程序的流程非常清楚,可以实现多个回调。

先在ES6出来之后,许多浏览器已经支持Promise方法,
这里写图片描述
promise有三种状态:

  1. pending:初始状态

  2. fulfilled:成功操作

  3. rejected:失败操作

    开始的时候promise是pending状态,fulfill之后就会执行回调then的回调函数,如果是reject就会调用catch进行异常处理,Promise.prototype.then() Promise.prototype.catch() 两种方法状态都会返回一个promise对象,用于后续链式调用。

建立一个promise例子

    
'use strict';var promiseCount = 0;function testPromise(){    var thisPromiseCount = promiseCount++;    var log = document.getElementById('log');    log.insertAdjacentHTML('beforeend', thisPromiseCount +         ') 开始 (异步调用开始)
'); //新建一个promsie对象 var p1 = new Promise(function(resolve, reject){ log.insertAdjacentHTML('beforeend', thisPromiseCount + ') Promise 开始执行 (异步调用开始)
'); window.setTimeout(function(){ resolve(thisPromiseCount); }, 2000) }); //定义promise执行fulfilled执行的then()回调函数以及执行reject后的catch回调函数 p1.then( function(val) { log.insertAdjacentHTML('beforeend', val + ') Promise fulfilled (异步代码中断)
'); }) .catch( function(reason) { console.log('Handle rejected promise ('+reason+') here.'); }); log.insertAdjacentHTML('beforeend', thisPromiseCount + ') 建立promise'); }if ("Promise" in window) { var btn = document.getElementById("btn"); btn.addEventListener("click",testPromise); } else { log = document.getElementById('log'); log.innerHTML = "浏览器不支持promise接口"; }}

单击按钮后,首先执行promise

这里写图片描述

3秒之后resolve调用then()方法

这里写图片描述

实现XMLHttpRequest获取数据

使用ajax异步加载图片

function imgLoad(url) {    //返回promsie对象    return new Promise(function(resolve, reject) {      var xhr = new XMLHttpRequest();      xhr.open('GET', url);      xhr.responseType = 'blob';      xhr.onload = function() {        if (xhr.status === 200) {          resolve(xhr.response);        } else {          reject(Error('图像加载失败; 错误原因:' + xhr.statusText));        }      };      xhr.onerror = function() {          reject(Error('加载错误.'));      };      xhr.send();    });  }    var body = document.querySelector('body');  var myImage = new Image();  var url = 'http://7qnb7a.com1.z0.glb.clouddn.com/6608717992840918931.jpg';  imgLoad(url).then(function(response) {     var imageURL = window.URL.createObjectURL(response);     myImage.src = imageURL;     body.appendChild(myImage);  }, function(Error) {    console.log(Error);  });

这里写图片描述

构建一个简单的promise模式框架

  • 首先需要建立一个对象来存储promise

Promise = function(){    this.queue = [];    this.value = null;    this.status = 'pending';};
  • 定义获取队列,设定状态和获取状态原型方法

Promsie.prototype.getQueue = function(){    return this.queue;};Promise.prototype.getStatus = function(){    return this.status;};Promise.prototype.setStatus = function(s, value){    if(s === 'fulfilled' || s === 'rejected'){        this.status = s;        this.value = value || null;        this.queue = [];        var freezeObject = Object.freeze || function(){};        freezeObject(this);    }else{        throw new Error({message:"doesn't support status: "+s});    }};
  • 定义then方法,接受两个参数用于完成和拒绝任务操作。

Promise.prototype.then = function(onFulfilled, onRejected){    var handler = {        'fulfilled': onFulfilled,        'rejected': onRejected    };    handler.deferred = new Deferred();    if(!this.isPending()){        utils.procedure(this.status, handler, this.value);    }else{        this.queue.push(handler);    }    return handler.deferred.promise;};
  • 定义三个不同状态函数

Promise.prototype.isFulfilled = function(){    return this.status === 'fulfilled';};Promise.prototype.isRejected = function(){    return this.status === 'rejected';};Promise.prototype.isPending = function(){    return this.status === 'pending';};
  • 工具处理函数

var utils = (function(){    var makeSignaler = function(deferred, type){        return function(result){            transition(deferred, type, result);        }    };        var procedure = function(type, handler, result){        var func = handler[type];        var def = handler.deferred;        if(func){            try{                var newResult = func(result);                if(newResult && typeof newResult.then === 'function'){                    newResult.then(makeSignaler(def, 'fulfilled'), makeSignaler(def, 'rejected'));                }else{transition(def, type, newResult);}            }catch(err){transition(def, 'rejected', err);}        }else{transition(def, type, result);}    };    var transition = function(deferred, type, result){        if(type === 'fulfilled'){            deferred.resolve(result);        }else if(type === 'rejected'){            deferred.reject(result);        }else if(type !== 'pending'){            throw new Error({'messgae':"doesn,t support type:"+type});        }     };    return {        'procedure': procedure    }})();
  • 定义延迟函数

Deferred = function() {    this.promise = new Promise();};Deferred.prototype.resolve = function(result) {    if (!this.promise.isPending()) {        return;    }    var queue = this.promise.getQueue();    for (var i = 0, len = queue.length; i < len; i++) {        utils.procedure('fulfilled', queue[i], result);    }    this.promise.setStatus('fulfilled', result);};Deferred.prototype.reject = function(err) {    if (!this.promise.isPending()) {        return;    }    var queue = this.promise.getQueue();    for (var i = 0, len = queue.length; i < len; i++) {        utils.procedure('rejected', queue[i], err);    }    this.promise.setStatus('rejected', err);}

有很多实现了promises的库供开发者可用。 像jQuery的 Deferred, 微软的 WinJS.Promise, when.js, q, 和dojo.Deferred.

关于jQuery的Deferred可以参考

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

你可能感兴趣的文章
详细探究Spark的shuffle实现
查看>>
我的友情链接
查看>>
提取android apk文件中的dat格式的图片资源
查看>>
windows 2003下 mysql安装时 MySQL Apply Security Settings安装不成功的解决方案
查看>>
【Oauth认证】使用scribe实现OAUTH
查看>>
ASP.NET Razor Pages API Quick Reference
查看>>
Chirp Chirp: Visual Studio Add-In for DotLess, Js, and Css Files
查看>>
安装MySQL5.6出现的问题
查看>>
我的友情链接
查看>>
cocos2dx程序启动过程,和跨平台实现
查看>>
75、分发系统|expect脚本远程登录和执行命令、传递参数
查看>>
系统集成资质培训 - 英语题目练习(0511)
查看>>
SSH连接速度慢
查看>>
Android ADB 常用命令
查看>>
Nagios/Cacti异常报警,设定总动清理内存
查看>>
HA(高可用)集群之AIS(corosync),高可用httpd+NFS
查看>>
我的友情链接
查看>>
我的友情链接
查看>>
centos知识点巩固
查看>>
我的友情链接
查看>>