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

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

本篇文章通过构建一个简单的Promise对象来了解如何做到异步获得数据。

使用方法

const fetch = function(url) {  return new Promise((resolve, reject) => {    request((error, apiResponse) => {      if (error) {         //返回为error的时候,调用reject函数        reject(error)      }      // 有数据返回的时候,调用resolve      resolve(apiResponse)    })  })}

这个fetch()的方法返回了一个Promise对象,接着我们就可以用then来对获得的数据进行处理,catch来捕获可能的错误。

Promise的简单实现

首先,我们要知道Promise实际上是一个对象,当我们运行下面的代码可以发现返回true。

console.log(typeof new Promise((resolve, reject) => {}) === 'object') // true

接着要构建一个Promise类,来生成Promise Object。

思路:

在constructor 里面传入executionFunction, 然后将onResolve,onReject映射到里面,then主要做一件事情,就是将onResolve的函数收集起来,在this.onResolve里面一起调用,每次返回的值都覆盖前一次的。

说的什么玩意儿,眼见为实下面来看一下代码:

class PromiseSimple{    constructor(executionFunction) {        this.promiseChain = [];        this.onResolve = this.onResolve.bind(this)        this.onReject = this.onReject.bind(this)        this.handleError = () => {}        // 外界传入的函数我们将其定义为executionFunction,将里面        // 的onResolve onReject 映射到this.onResolve, this.onReject        executionFunction(this.onResolve, this.onReject)    }    then(onResolve) {        // 收集状态成功的时候的回调函数        this.promiseChain.push(onResolve)        return this    }     catch(onReject) {        this.handleError = onReject        return this    }    onResolve(value) {    var storedValue = value;    try {        // 在resolve里面执行        this.promiseChain.forEach((executePromise) => {            storedValue = executePromise(storedValue)        })    } catch(error){        this.promiseChain = [];        this.onReject(error)    }    }    onReject(error) {        this.handleError(error)    }}

梳理一下,其实只要记住其中两点:

1、这个对象有四个方法then catch onResolve onReject,它们的作用分别是

  • then

    用来收集有数据的时候的回调函数,放在this.promiseChain里,注意这里要返回this

对象才能实现链式调用

  • catch

    用来处理出现的error,注意这里要返回this对象实现链式调用

  • onResolve

    依次执行then里面收集的回调函数,并且将回调函数的返回值在作为参数传给下一个回调函数

  • onReject

    用来处理出现的error

2、then catch 必须要返回this,才能实现链式调用

这样我们一个简单的Promise 对象就做好了

下面可以用这个来玩一玩

class PromiseSimple {  constructor(executionFunction) {    this.promiseChain = [];    this.handleError = () => {};    this.onResolve = this.onResolve.bind(this);    this.onReject = this.onReject.bind(this);    executionFunction(this.onResolve, this.onReject);  }  then(onResolve) {    this.promiseChain.push(onResolve);    return this;  }  catch(handleError) {    this.handleError = handleError;    return this;  }  onResolve(value) {    let storedValue = value;    try {      this.promiseChain.forEach((nextFunction) => {         storedValue = nextFunction(storedValue);      });    } catch (error) {      this.promiseChain = [];      this.onReject(error);    }  }  onReject(error) {    this.handleError(error);  }}fakeApiBackend = () => {  const user = {    username: 'treyhuffine',    favoriteNumber: 42,    profile: 'https://gitconnected.com/treyhuffine'  };  // Introduce a randomizer to simulate the  // the probability of encountering an error  if (Math.random() > .05) {    return user;  } else {    const error = {      statusCode: 404,      message: 'Could not find user',      error: 'Not Found',    };        return error;  }};// Assume this is your AJAX library. Almost all newer// ones return a Promise Objectconst makeApiCall = () => {  return new PromiseSimple((resolve, reject) => {    // Use a timeout to simulate the network delay waiting for the response.    // This is THE reason you use a promise. It waits for the API to respond    // and after received, it executes code in the `then()` blocks in order.    // If it executed is immediately, there would be no data.    setTimeout(() => {      const apiResponse = fakeApiBackend();      if (apiResponse instanceof  Error) {        reject(apiResponse);      } else {        resolve(apiResponse);      }    }, 5000);  });};makeApiCall()  .then((user) => {    console.log('In the first .then()');      return user;  })  .then((user) => {    console.log(`User ${user.username}'s favorite number is ${user.favoriteNumber}`);      return user;  })  .then((user) => {    console.log('The previous .then() told you the favoriteNumber')      return user.profile;  })  .then((profile) => {    console.log(`The profile URL is ${profile}`);  })  .then(() => {    console.log('This is the last then()');  })  .catch((error) => {    console.log(error.message);  });

参考文档:

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

你可能感兴趣的文章
BI工具开发的主要内容
查看>>
建立个人站点之申请域名和空间
查看>>
使用docker配置etcd集群
查看>>
Flask学习 三 web表单
查看>>
web.config
查看>>
数组去重(new Set)
查看>>
requirejs的config及optimizer r.js配置
查看>>
一个电脑 两个显示屏
查看>>
win7如何共享文件 图文教你设置win7文件共享
查看>>
ubuntu安装mysql
查看>>
递归程序的非递归实现
查看>>
结合字符串常量池/String.intern()/String Table来谈一下你对java中String的理解
查看>>
Git使用笔记
查看>>
均值不等式使用变化
查看>>
tf.train.batch的偶尔乱序问题
查看>>
(转)深入理解最强桌面地图控件GMAP.NET --- 初用
查看>>
洛谷P4459/loj#2511 [BJOI2018]双人猜数游戏(博弈论)
查看>>
html5杂谈1
查看>>
阿里云 azkaban 发邮件的坑
查看>>
socket协议和http协议性能对比
查看>>