Promise

Promise基础

常见的方法

  • 静态方法(类上的方法,通过Promise.XXX调用)
    • Promise.all()
    • Promise.resolve()
    • Promise.reject()
    • Promise.race()
  • 动态方法(原型上的方法,通过new Promise().XXX调用)
    • new Promise().then()
    • new Promise().catch()
    • new Promise().finally()

常见方法的用法

  • 1.new Promise() && new Promise().then()
    • 如图可以看出我们执行new Promise()的时候需要传进去一个executor执行器(函数),并且会立即执行;包含两个参数一个是resolve,一个是reject这两个参数依然是函数
    • executor函数会立即执行
    • 默认的状态是pendding
      • 注:Promise一共有三种状态,等待态:pendding 、成功态:fulfilled、失败态:rejected
    • 调用executor中的resolve方法代表成功态
    • 调用executor中的reject方法代表失败态
    • 可以从等待态(pendding)转化成成功态(fulfill)/失败态(reject);不可以从成功态/失败态向其他状态转化
  • 简易实现(仅支持同步)
function Promise(executor) { //1.传入executor
  let self = this;
  self.status = 'pending'; //5.在Promise内部中定义一个变量用来表示当前promise的状态 
  self.value = null; //6.记录resolve执行传入的value
  self.reason = null; //7.记录reject执行传入的reason
  function resolve(value) {  //3.调用resolve会传入一个value
    if (self.status !== 'pending') return;
    self.status = 'fulfilled';
    self.value = value;
  }

  function reject(reason) {  // 4.调用reject会传入一个reason
    if (self.status !== 'pending') return;
    self.status = 'rejected';
    self.reason = reason;
  }
  executor(resolve, reject)  //2.executor立即执行,传入两个方法resolve,reject
}

/*在Promise的原型上有一个then方法,then方法执行会传入两个函数onFulfilled && onRejected;*/
Promise.prototype.then = function (onFulfilled, onRejected) {
  let self = this;
  if (self.status === 'fulfilled') {  // promise的状态为fulfilled的时候onFulfilled执行
    onFulfilled(self.value);
  }
  if (self.status === 'rejected') {   // promise的状态为rejected的时候onFulfilled执行
    onRejected(self.reason);
  }
}
module.exports = Promise;
复制代码
  • 升级实现(支持异步)
    • 上述的代码中我们实现了executor函数管理同步的方法,并没有对exctutor函数中管理的异步代码进行实现;即不是立即执行resolve 或者reject方法的时候(也就是说then方法中如果状态是pendding的时候我们怎么处理)
function Promise(executor) {
  let self = this;
  self.status = 'pending';
  self.value = null;
  self.reason = null;
  self.onFulfilledCallback = [];
  self.onRejectedCallback = [];

  function resolve(value) {
    if (self.status !== 'pending') return;
    self.status = 'fulfilled';
    self.value = value;
    self.onFulfilledCallback.forEach(fn => fn());
  }
  function reject(reason) {
    if (self.status !== 'pending') return;
    self.status = 'rejected';
    self.reason = reason;
    self.onRejectedCallback.forEach(fn => fn());
  }
  executor(resolve, reject);
}

Promise.prototype.then = function (onFulfilled, onRejected) {
  let self = this;
  if (self.status === 'fulfilled') {
    onFulfilled(self.value);
  }
  if (self.status === 'rejected') {
    onRejected(self.reason);
  }
  if (self.status === 'pending') {
    self.onFulfilledCallback.push(function () {
      onFulfilled(self.value);
    });

    self.onRejectedCallback.push(function () {
      onRejected(self.reason);
    })
  }
}

module.exports = Promise;
复制代码

PeomiseA+实现

- 我们知道`Promise`最大的优点就是通过链式调用,解决回调地狱(恶魔金字塔)
- 链式调用的特点
    - 1.如果一个`then`中方法返回普通值,那么这个值会传递给下一个`then`的`onFullfilled`的输入
    - 2.如果一个`then`返回的是报错,那么这个错误信息会传递给下一个`then`的`onRejected`的输入
    - 3.如果返回的是一个`Promise`,那么这个`Promise`的成功或者失败决定下一个`then`调用的方法
    - 4.捕获错误机制
        - 默认会找离自己最近的`then`的失败,找不到继续向下找,最后找不到抛错
- 实现原理
    - 1.`promise`调用`then`方法会返回一个新的`Promise2`;
    - 2.拿到当前`then`方法中成功(`onFulfilled`)或者失败(`onRejected`)执行返回的结果`x`
    - 3.判断`then`方法返回的`promise2`和成功(`onFulfilled`)或者失败(`onRejected`)执行返回的结果`x`的关系
        - 1).如果`promise === x` 抛出循环引用错误
复制代码
function Promise(executor) {
    let self = this;
    self.status = 'pending';
    self.value = null;
    self.reason = null;
    self.onFulfilledCallback = [];
    self.onRejectedCallback = [];
    function resolve(value) {
        if(value instanceof Promise){
            value.then(y=>{
                resolve(y);
            },r=>{
                reject(r);
            })
        }
        if (self.status === 'pending') {
             self.status = 'fulfilled';
             self.value = value;
             self.onFulfilledCallback.forEach(fn => fn());
        };
       
    }

    function reject(reason) {
        if (self.status === 'pending') {
            self.status = 'rejected';
            self.reason = reason;
            self.onRejectedCallback.forEach(fn => fn());
        };
    }
    try{
        executor(resolve, reject);
    }catch(err){
        reject(err);
    }
}

function resolvePromise(promise2, x, resolve, reject) {
    if (promise2 === x) {
       reject(new TypeError('Circular Reference'));
    }
    if (x !== null && typeof x === 'object' || typeof x === 'function') {
        let called;
        try {
            let then = x.then;
            if (typeof then === 'function') {
                then.call(x, (y) => {
                    if (called) return;
                    called = true;
                    resolvePromise(promise2, y, resolve, reject);
                    // resolve(y);
                }, (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 : value => value;
    onRejected = typeof onRejected === 'function' ?onRejected : err => {throw err};
    let promise2 = new Promise(function (resolve, reject) {
        if (self.status === 'fulfilled') {
            setTimeout(() => {
                try {
                    let x = onFulfilled(self.value);
                    resolvePromise(promise2, x, resolve, reject);
                } catch (e) {
                    reject(e);
                }
            }, 0)
        }
        if (self.status === 'rejected') {
            setTimeout(() => {
                try {
                    let x = onRejected(self.reason);;
                    resolvePromise(promise2, x, resolve, reject);
                } catch (e) {
                    reject(e);
                }
            }, 0)

        }
        if (self.status === 'pending') {
            self.onFulfilledCallback.push(function () {
                setTimeout(() => {
                    try {
                        let x = onFulfilled(self.value);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                }, 0)
            })
            self.onRejectedCallback.push(function () {
                setTimeout(() => {
                    try {
                        let x = onRejected(self.reason);;
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                }, 0)
            })
        }
    })
    return promise2;
}

/*实现一个Promise的defer对象*/
Promise.defer = function(){
    let dfd = {};
    dfd.promise = new Promise((resolve,reject)=>{
        dfd.resolve = resolve;
        dfd.reject = reject;
    })
    return dfd;
}

module.exports = Promise;
复制代码

注:上述代码实现过程中我们需要注意的几点说明:

  • 1.放到setTimeout中,原因是:当我们new Promise()执行的时候传入的excutor函数会立即执行,并且返回promise2,但是如果我们不放到setTimeout中我们是拿不到返回的promise2的,因为函数还没有执行完,并没有返回值,至于为什么放到setTimeou中可以拿到就涉及到了js代码的执行机制以及宏任务微任务的一些知识了,这里我就不做过多赘述了
  • 2.细心的朋友应该可以看到我代码中注释掉了resolve(y),而是递归调用了resolvePromise(promise2,y,resolve,reject),原因很简单就是当我们使用promise.then调用resolve()的时候可能继续传进去一个promise
  • 3.called,使用called的原因就更简单了,就是我们的promise可能会出现和别人的promise一起使用的情况,加called就是为了防止别人的代码没有实现非pending状态不能向其他状态转变的情况

验证是否符合PromiseA+规范

  • 使用官方提供的库promises-aplus-tests
  • 1.全局安装npm install promises-aplus-tests -g
  • 2.通过promises-aplus-tests xxx(需要测试的文件)命令进行测试
  • 3.要求测试的时候要有Promise.deferred,这就是我们代码中Promise.deffered的一个别名,加上即可(我这里就不添加了,你们贴过去测一下就会看到效果)

A+规范中的Promise常见方法实现

类上的方法

Promise.resolve()
Promise.resolve = function(value){
    return new Promise((reslove,reject)=>{
        reslove(value)
    })
}
复制代码
Promise.reject()
Promise.reject = function(reason){
    return new Promise((resolve,reject)=>{
        reject(reason)
    })
}
复制代码
Promise.all()
Promise.all = function(promises){
    return new Promise((resolve,reject)=>{
        let arr = [];
        let i = 0;
        function processData(index,value){
            arr[index] = value;
            if(++i === promises.length){
                resolve(arr);
            }
        }
        for(let i = 0; i < promises.length; i++){
            let current = promises[i];
            if(current !== null &&typeof current === 'object' || typeof current === 'function'){
                let then = x.then;
                if(typeof then === 'function'){
                    current.then(value=>{
                        processData(i,value);
                    },reject);
                }else{
                    processData(i,current);
                }
            }else{
                processData(i,current);
            }
        }
    })
}
复制代码
Promise.race()
Promise.race = function(promises){
    return new Promise((resolve,reject)=>{
        for(let i = 0; i < promises.length; i++){
            let current = promises[i]; 
            if(current !== null && typeof current === 'object' || typeof current === 'function'){
                let then = current.then;
                if(typeof then === 'function'){
                    current.then(resolve,reject);
                }else{
                    resolve(current)
                }
            }else{
                resolve(current)
            }
        }
    })
}
复制代码

原型上的方法

Promise.prototype.catch
Promise.prototype.catch = function(errCallback){
    return this.then(null,errCallback);
}
复制代码

Promise.prototype.finally

Promise.prototype.finally = function(callback){
    return this.then(value=>{
        callback();
        return value;
    },reason=>{
        callback();
        return reason;
    })
}
复制代码

转载于:https://juejin.im/post/5c6fc5ad51882562276c45ce

基于数据挖掘的音乐推荐系统设计与实现 需要一个代码说明,不需要论文 采用python语言,django框架,mysql数据库开发 编程环境:pycharm,mysql8.0 系统分为前台+后台模式开发 网站前台: 用户注册, 登录 搜索音乐,音乐欣赏(可以在线进行播放) 用户登陆时选择相关感兴趣的音乐风格 音乐收藏 音乐推荐算法:(重点) 本课题需要大量用户行为(如播放记录、收藏列表)、音乐特征(如音频特征、歌曲元数据)等数据 (1)根据用户之间相似性或关联性,给一个用户推荐与其相似或有关联的其他用户所感兴趣的音乐; (2)根据音乐之间的相似性或关联性,给一个用户推荐与其感兴趣的音乐相似或有关联的其他音乐。 基于用户的推荐和基于物品的推荐 其中基于用户的推荐是基于用户的相似度找出相似相似用户,然后向目标用户推荐其相似用户喜欢的东西(和你类似的人也喜欢**东西); 而基于物品的推荐是基于物品的相似度找出相似的物品做推荐(喜欢该音乐的人还喜欢了**音乐); 管理员 管理员信息管理 注册用户管理,审核 音乐爬虫(爬虫方式爬取网站音乐数据) 音乐信息管理(上传歌曲MP3,以便前台播放) 音乐收藏管理 用户 用户资料修改 我的音乐收藏 完整前后端源码,部署后可正常运行! 环境说明 开发语言:python后端 python版本:3.7 数据库:mysql 5.7+ 数据库工具:Navicat11+ 开发软件:pycharm
MPU6050是一款广泛应用在无人机、机器人和运动设备中的六轴姿态传感器,它集成了三轴陀螺仪和三轴加速度计。这款传感器能够实时监测并提供设备的角速度和线性加速度数据,对于理解物体的动态运动状态至关重要。在Arduino平台上,通过特定的库文件可以方便地与MPU6050进行通信,获取并解析传感器数据。 `MPU6050.cpp`和`MPU6050.h`是Arduino库的关键组成部分。`MPU6050.h`是头文件,包含了定义传感器接口和函数声明。它定义了类`MPU6050`,该类包含了初始化传感器、读取数据等方法。例如,`begin()`函数用于设置传感器的工作模式和I2C地址,`getAcceleration()`和`getGyroscope()`则分别用于获取加速度和角速度数据。 在Arduino项目中,首先需要包含`MPU6050.h`头文件,然后创建`MPU6050`对象,并调用`begin()`函数初始化传感器。之后,可以通过循环调用`getAcceleration()`和`getGyroscope()`来不断更新传感器读数。为了处理这些原始数据,通常还需要进行校准和滤波,以消除噪声和漂移。 I2C通信协议是MPU6050与Arduino交互的基础,它是一种低引脚数的串行通信协议,允许多个设备共享一对数据线。Arduino板上的Wire库提供了I2C通信的底层支持,使得用户无需深入了解通信细节,就能方便地与MPU6050交互。 MPU6050传感器的数据包括加速度(X、Y、Z轴)和角速度(同样为X、Y、Z轴)。加速度数据可以用来计算物体的静态位置和动态运动,而角速度数据则能反映物体转动的速度。结合这两个数据,可以进一步计算出物体的姿态(如角度和角速度变化)。 在嵌入式开发领域,特别是使用STM32微控制器时,也可以找到类似的库来驱动MPU6050。STM32通常具有更强大的处理能力和更多的GPIO口,可以实现更复杂的控制算法。然而,基本的传感器操作流程和数据处理原理与Arduino平台相似。 在实际应用中,除了基本的传感器读取,还可能涉及到温度补偿、低功耗模式设置、DMP(数字运动处理器)功能的利用等高级特性。DMP可以帮助处理传感器数据,实现更高级的运动估计,减轻主控制器的计算负担。 MPU6050是一个强大的六轴传感器,广泛应用于各种需要实时运动追踪的项目中。通过 Arduino 或 STM32 的库文件,开发者可以轻松地与传感器交互,获取并处理数据,实现各种创新应用。博客和其他开源资源是学习和解决问题的重要途径,通过这些资源,开发者可以获得关于MPU6050的详细信息和实践指南
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值