精华内容
下载资源
问答
  • 今天的这篇文章主要是总结promise对象如何实现同步处理异步任务: 我从头开始慢慢介绍这个过程吧!这个过程我会代码一一实现,毕竟文字不如 代码来得合适。 promise的三种状态 //pending 准备阶段 //fulfilled ...

    今天的这篇文章主要是总结promise对象如何实现同步处理异步任务:

    我从头开始慢慢介绍这个过程吧!这个过程我会用代码一一实现,毕竟文字不如 代码来得合适。

    promise的三种状态

    //pending 准备阶段
    //fulfilled 成功
    //rejected  失败
    function promise() {
        return new Promise((resolve, reject) => {
            resolve("成功");
            // reject("失败");
        })
    }
    console.log(promise()); //Promise {<pending>} 没调用微任务之前
    // console.log(promise()); // Promise {<fulfilled>: "成功"} 调用resolve
    // console.log(promise()); //Promise {<rejected>: "失败"} 调用reject
    

    Promise对象的任务进行抛出(一般我们就定义reslove成功reject失败)并通过thencatch关键字进行处理:

    //可以将任务处理模块(resolve或reject)多次抛出
    //以then或者catch结束(必须有处理模块,放一个空的then是无效的)来获取这个结果并会结束此次任务
    let p1 = new Promise((resolve, reject) => {
        // resolve("成功");
        reject("失败")
    })
    new Promise((resolve, reject) => {
        resolve(p1)
    }).then(
        value => {
            console.log(value);
        },
        reason => {
            console.log("error" + reason);
        }
    ).catch(error => {
        console.log(error); //这里不能再次获取失败内容,因为在上面已获取了一次了
    })
    

    我们要记住默认情况下.then返回的promise对象抛出的是成功状态

    let p1 = new Promise((resolve, reject) => {
        // resolve("fulfilled");
        reject("reject");
    });
    //可以通过一个变量存储p1这个promise对象
    let p2 = p1
    .then(
        value => console.log("成功" + value),
        error => console.log("失败" + error)
    )
    .then(
        //会输出 但不会得到a值,它是undefined,因为在上面已经接受了
        a => console.log("最后的成功" + a), //最后的成功undefined
        //不会执行,默认情况下.then返回的是成功的,只会打印resolve语句
        b => console.log("最后的失败" + b)
    ).then(
        //依旧会执行 a此时为undefined
        a => console.log("11" + a) //11undefined
    )
    

    总之一句话,.then就是对返回的前一个promise对象进行处理,默认.then返回的是成功的promise对象

    let p1 = new Promise((resolve, reject) => {
       resolve("第一次成功");
    });
    p1.then(
        // value => 123, //这里可以是一个返回值,让下一个then去处理这个值
        //当然这里也可以嵌套一个promise对象
        value => {
            console.log(value); //接受第一次成功
            return new Promise((resolve, reject) => {
                resolve("第二次成功")
            })
        },
        error => console.log(error) //不会输出 没有错误reject抛出
    ).then(
        //通过这样来处理前面的返回值
        //实现了嵌套promise对象的模块
        res => console.log("拿到前面的返回值" + res), //拿到前面的返回值第二次成功
        err => console.log(err) //对前面返回值中抛出错误处理
    )
    

    好了我们可以稍稍深入一点点了,我们从上面的代码也能看出,异步任务是可以通过Promise对象去使之变成同步任务的,我们可以把这些同步任务称为队列,下面的代码或许更加明朗一些:

    let promise = Promise.resolve("123"); //下面有介绍哦
    promise = promise.then(
        value => {
            return new Promise(resolve => {
                setTimeout(() => {
                    console.log(value);
                    resolve("ab")
                }, 1000);
            })
    
        }
    );
    //实际得到就是上一个promise返回值赋值给一个变量罢了 跟直接用then差不多的
    promise.then(
        v => {
            return new Promise(resolve => {
                setTimeout(() => {
                    console.log(v);
                    resolve("ab")
                }, 1000);
            })
        }
    )
    

    上述Promise.resolve("123");实际上就是以下代码的简写了,可以试试看,得出来的结果是一样的:

    new Promise(resolve => {
    	reslove("123");
    }.then(
    	res => console.log(res);  //"123"
    )
    
    Promise.resolve("123").then(res => console.log(res)) //"123"
    

    这里的原理要理解清楚,下面就是对其的拓展了;

    ----------------数组实现队列(相当于同步任务,依次执行)
    其实这也是一个异步任务:
    数组map方式实现:

    let arr = [1, 2, 3, 4, 5];
    //封装成函数 map方式 封装队列
    function queue(arr) {
        let promise = Promise.resolve();
        //循环给promise赋值,使其同步输出
        arr.map(v => {
            promise = promise.then(_ => {
                return new Promise(resolve => {
                    setTimeout(() => {
                        console.log(v); //这里会依次去打印1,2,3,4,5每次间隔时间为1秒
                        resolve();
                    }, 1000)
                })
            }
            )
        })
    }
    queue(arr);
    

    这样写的话,我们大大减少了之前用链式then依次输出的代码量,而且我感觉这样的代码看起来还是有点牛皮哈! 哈哈

    reduce实现队列:其核心跟map是差不多的,需要了解这种方法的使用,不清楚的伙伴可以去看数组的八种遍历方式

    //使用reduce 封装队列
    let arr = [1, 2, 3, 4, 5];
    arr.reduce((promise, n) => {
        return promise.then(_ => {
            return new Promise(resolve => {
                setTimeout(() => {
                    console.log(n); //这里也会依次去打印1,2,3,4,5每次间隔时间为1秒
                    resolve()
                }, 1000)
            })
        })
    }, Promise.resolve())
    

    好了,文章就到此结束了,这个也是偶然看视频获得一些总结,希望大家多多支持啊!!!

    展开全文
  •  我现在是一边喝着红牛一边写着博客,好了好了,不扯了,回归整体好吧  先简单来说一下啥是promise吧  它是什么?...可以把一个多层嵌套的同步、异步都有回调的方法,给拉直为一串.then()组成的调...

       我又又又回来了,最近真是累的跟狗一样,急需一个大保健回复一下子精力

       我现在是一边喝着红牛一边写着博客,好了好了,不扯了,回归整体好吧

       先简单来说一下啥是promise吧

       它是什么?Promise是一个方案,用来解决多层回调嵌套的解决方案。它现在是ES6的原生对象。

          干嘛用的?可以把一个多层嵌套的同步、异步都有回调的方法,给拉直为一串.then()组成的调用链。

        解决啥问题?多层嵌套的回调方法中,如果同时存在同步、异步的方法,那么实际执行顺序会混乱。不好调试不好维护

       现在我们再来说一说自己写简单的promise的思路,我们是如何将异步函数同步执行的呢,正常情况下,我们只需要用函数

       嵌套就可以解决,但是现在我们要封装一个promise,那我们要怎么做呢,其实原理还是一样的,只要能在第一个函数执行完

       再调用下一个函数不就可以了嘛   

       下面还是直接上代码

       

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
    </head>
    
    <body>
        <script>
            function MyPromise(func) {
                var self = this;
                var count = 0;
                this.cbklist = [];
                this.then = function (callback) {
                    //将所有.then方法传进来的参数push到数组当中
                    this.cbklist.push(callback);
                    //能实现链式调用的关键
                    return this;
                }
                this.success = function () {
                    //使用递归调用自身
                    if (count == self.cbklist.length) return;
                    self.cbklist[count++](self.success);
    
                }
                //进来时调用第一个函数
                func(self.success);
            }
    
    
            // 下面是调用的例子
            function ajaxA(success) {
                setTimeout(function () {
                    console.log("AAAAAAAAAA");
                    success();
                }, 3000);
            }
    
            function ajaxB(success) {
                setTimeout(function () {
                    console.log("BBBBBBBBBB");
                    success();
                }, 2000);
            }
    
            function ajaxC(success) {
                setTimeout(function () {
                    console.log("CCCCCCCCCC");
                    success();
                }, 6000);
            }
    
            function ajaxD() {
                setTimeout(function () {
                    console.log("DDDDDDDDD");
                }, 2000);
            }
            new MyPromise(ajaxA).then(ajaxB).then(ajaxC).then(ajaxD);
        </script>
    </body>
    
    </html>

     

     

      

    转载于:https://www.cnblogs.com/suihang/p/9900581.html

    展开全文
  • 为啥要用Promise来表示异步的结果?而不用其他方式呢? 什么是异步 用一个例子来说明 当你再餐厅吃饭,首先你的先去排队拿号, 但是,你前面还有10桌需要等待,可能需要几十分钟, 如果你在这里傻等,那就是同步操作...
    Promise 是什么?

    mdn:Promise 对象用于表示一个异步操作的最终完成 (或失败)及其结果值。
    既然Promise是为了表示异步的最终结果,那异步是什么呢?为啥要用Promise来表示异步的结果?而不用其他方式呢?

    什么是异步

    用一个例子来说明
    当你在餐厅吃饭,首先你得先去排队拿号,
    但是,你前面还有10桌需要等待,可能需要几十分钟,
    如果你在这里傻等,那就是同步操作,
    但正常人没那么傻,大部分人都是先拿票,然后去点其他事情,这就是异步操作
    那如何知道是否轮到自己?

    1. 隔一会去拿票的地方问(轮询)
    2. 用微信小程序接收通知(回调)

    异步即立即拿不到结果需要通过回调和轮询来获取异步操作的结果
    下面是一些异步操作的典型案例

    1. setTimeout
    2. AJAX
    3. AddEventListener
    获取异步的结果
    1. 回调callback
      用微信小程序接收通知
    function 排队(号码, 到我了吗){
        if(号码轮到我了){
            return 到我了吗('快来吃饭啦');
        }
      }
      function 到我了吗(到我了吗){
        return '快来吃饭啦';
      }
    
    1. 轮询
      隔一会去拿票的地方问
    //设置定时器,每隔20分钟去问一次
    const 排队吃饭 = setInterval(() => {
        if (结果 === '到我啦') {
            //到我了就去吃饭,清除计时器,停止轮询
            clearInterval(this.timeId)
        }; 
        问前台轮到我了吗();
    }, 1000*60*20)
    
    为啥要使用Promise

    既然轮询和回调都可以拿到结果,为啥要用promise呢
    异步的结果可能会有两种,一是成功,二是失败,所以我们要么使用两个回调,要么回调接收两个参数

    //回调接受两个参数
    fs.readFile('./1.txt', (error, data) => {
        if (error) {
            console.log('失败');//失败返回失败信息
            return
        }
        console.log(data.toString())//成功返回数据结果
    })
    //用两个回调来接受结果
    ajax('get','/1.json', data=>{}, error=>{})
    //回调地狱(仅4层的回调?如果更多呢?)
    getUser(user => {
        getGroups(user, (groups) => {
            groups.forEach((g) => {
                g.filter(x => x.ownerId === user.id)
                    .forEach(x => console.log(x))
            })
        })
    })
    

    缺点:

    1. 回调参数的命名没有明确规定
    2. 回调一多,容易出现回调地狱
    3. 很难进行错误处理
    Promise

    前面两种方法都有一些缺陷,而Promise的设计思想刚好又解决了这些缺陷
    Promise的原理:使用resolve, reject两个函数控制Promise内部成功和失败状态,promise.then()根据成功和失败执行不同的函数,实现异步

    1. 创建Promise对象
    new Promise((resolve,reject)=>{})
    
    1. Promise.prototype.then
    //通过then函数传入成功和失败的执行操作,success不可省略,fail可省略
    new Promise((resolve,reject)=>{}).then(success,fail)
    
    1. Promise.all
      将多个Promise实例包装成一个新的Promise实例,实例全部成功则返回数组,实例失败则返回第一个失败的状态值
    Promise.all可以let obj = new Promise((resolve,reject)=>{resolve('成功')})
    let obj1 = new Promise((resolve,reject)=>{resolve('成功')})
    let obj2 = new Promise((resolve,reject)=>{reject('失败')})
    //执行结果["成功", "成功"]
    Promise.all([obj,obj1]).then((result) => {
      console.log(result)
    }).catch((error) => {
      console.log(error)    
    })
    //执行结果 失败
    Promise.all([obj,obj2]).then((result) => {
      console.log(result)
    }).catch((error) => {
      console.log(error)    
    })
    
    1. promise.race,获取多个实例中执行最快的那个实例的返回结果(不管处于成功状态和失败状态)
    let obj = new Promise((resolve,reject)=>{
       setTimeout(() => {
           resolve('成功')
         }, 500)
       
    })
    let obj1 = new Promise((resolve,reject)=>{
       setTimeout(() => {
           reject('失败')
         }, 1000)   
    })
    //由于obj的执行时间较快,执行结果成功
    Promise.race([obj,obj1]).then((result) => {
     console.log(result)
    }).catch((error) => {
     console.log(error)    
    })
    

    手写简易版Promise

    实现思路:Promise内部定义两个队列,用于存放用户传过来的成功或失败之后的函数,提供resolve和reject用于成功和失败之后执行队列中的函数

    class Promise2{
        //创建两个队列用于存放成功或失败后要执行的函数
        queue1 = []
        queue2 = []
        constructor(fn){
            //成功函数
            const resolve = (data) =>{
                //执行队列中的函数
                setTimeout(()=>{
                    for(let i =0;i< this.queue1.length;i++){
                        this.queue1[i](data)
                    }
                })
            }
            //失败函数
            const reject = (reason) =>{
                setTimeout(()=>{
                    for(let i = 0; i< this.queue2.length;i++){
                        this.queue2[i](reason)
                    }
                })
            }
            fn(resolve,reject);
        }
        then(s,e){
            this.queue1.push(s);
            this.queue2.push(e);
            return this
        }
    }
    
    var p1 = new Promise2((resolve,reject)=>{console.log('hi');resolve();})
    p1.then(()=>{ console.log('成功')})
    
    展开全文
  • 启发自一月份的时候参加的某司的前端面试,当时我在和面试官聊项目经历的时候,谈到了Promise,引出了面试官此后长达半小时的对“如何用ES5的语法实现Promise”的灵魂拷问。因为答得不理想,所以今天就来补补课。 ...

    启发自一月份的时候参加的某司的前端面试,当时我在和面试官聊项目经历的时候,谈到了Promise,引出了面试官此后长达半小时的对“如何用ES5的语法实现Promise”的灵魂拷问。因为答得不理想,所以今天就来补补课。

    首先,来回顾一下Promise。Promise是ES6中提供的一个对象,能以同步、顺序的语句表达异步的操作。

    (MDN开发者文档对于Promise的描述:Promise - JavaScript | MSN。)

    下面是一个Promise的具体使用例子:

    const fn = function(resolve, reject) {
        console.log("Promise execution!");
        let date = new Date();
        let time = date.getTime();
        if (time % 2 == 0) {
            resolve("She loves me!");
        } else {
            reject("She doesn't love me!");
        }
    }
    
    const defer = new Promise(fn);
    
    defer.then(function(value) {
        console.log("resolve: " + value);
    }, function(reason) {
        console.log("reject: " + reason);
    });
    

    上述代码中,Promise对象的实例defer接收了fn函数作为参数。这里fn函数被称为executor函数,根据定义,“executor函数会在Promise构造函数返回新建的对象前被调用”。

    但是,我们注意到fn函数的定义中并没有对resolvereject这两个函数进行定义。那么,在执行fn函数语句的时候,这两个函数是如何得到执行的呢?

    此外,当程序运行到defer.then的时候,then函数的两个参数都是回调函数 ——分别记做onfulfilledonrejected—— 都与resolvereject函数有着千丝万缕的关系:当fulfilled的时候,调用onfulfilled函数,反之调用onrejected函数。
    (插一句,回调函数的记忆方式:callback: call then back. 调用之后返回主函数。)

    为了实现以上功能,我采取的方法是利用setTimeout函数,利用它的异步回调特性,来延迟resolvereject!。

    下面是我的实现:

    function NewPromise(fn) {
        this.value = null;
        this.resolveFn;
        this.rejectFn;
        // execute the fn function.
    	// bind NewPromise object onto resolve and reject funtcions, 
    	// so that the value of "this" keyword inside those two functions are both NewPromise object!
        fn(this.resolve.bind(this), this.reject.bind(this));
    }
    
    NewPromise.prototype.resolve = function(value) {
        this.value = value;
        setTimeout(() => {
            this.resolveFn(this.value);
        }, 0);
    }
    
    NewPromise.prototype.reject = function(reason) {
        this.value = reason;
        setTimeout(() => {
            this.rejectFn(this.value);
        }, 0);
    }
    
    NewPromise.prototype.then = function(resolveFn, rejectFn) {
        this.resolveFn = resolveFn;
        this.rejectFn = rejectFn;
    }
    
    const fn = (resolve, reject) => {
        console.log("Promise execution!");
        let date = new Date();
        let time = date.getTime();
        if (time % 2 == 0) {
            resolve("She loves me!");
        } else {
            reject("She doesn't love me!");
        }
    }
    
    const defer = new NewPromise(fn);
    
    defer.then((value) => {
        console.log("resolve: " + value);
    }, (reason) => {
        console.log("reject: " + reason);
    });
    

    上述代码中,fn函数首先在生成NewPromise对象的时候得到执行。但是由于在调用resolvereject的时候,使用了setTimeout函数,虽然只是延迟0秒执行,但是由于JavaScript的单线程 + 事件循环的特性,实际resolveFnrejectFn的调用必须等到主线程代码执行完毕才有机会开始。因此,主线程继续往下接着执行then函数,在then函数中,对NewPromise对象中的resolveFnrejectFn进行赋值。
    (这里resolveFnrejectFn只是得到了赋值,并没有执行!)

    then执行完毕后,主线程执行结束,再执行setTimeout中的回调函数resolveFn或者rejectFn,此时,resolveFnrejectFn已经被赋值,也顺利得到了valuereason的值。

    以上就是我用ES5的语法写的Promise初级版本(虽然使用了一部分ES6的箭头函数语法…)。总结起来就是利用setTimeout来延迟resolvereject函数的后半部分执行,前半部分对value赋值依旧正常执行,主线程结束后再利用resolve回调resolveFn,打印结果。(rejectFn同理。)

    附录:
    本文参考的文章:原文链接1原文链接2

    展开全文
  • 简要介绍:在多线程编程中,sleep的作用是起到挂起的作用,使线程休眠,而js是单线程的,我们如何在js中模拟sleep的效果呢~ 也就是如何用同步的方式来处理异步。 序:为什么不能用setTimeout来实现sleep的效果 ...
  • ES6 标准的 Promise 解决了 Javascript 代码中比较常见的回调地狱问题,搭配 async/await 可以用同步的方式写异步逻辑,大大提高了开发效率。 但是至今仍有很多库没有实现 Promise 化的接口,其中就包括微信小程序的...
  • 前言ES6 标准的 Promise 解决了 Javascript 代码中比较常见的回调地狱问题,搭配 async/await 可以用同步的方式写异步逻辑,大大提高了开发效率。但是至今仍有很多库没有实现 Promise 化的接口,其中就包括微信小...
  • 面试版同步异步编程

    2020-06-29 01:12:58
    面试版同步异步编程面试版同步异步编程1,什么情况下会用到多线程?2,什么是异步编程?同步编程又是什么?3,线程同步和异步主要解决了什么...7,既然你提到了 future 和 promise,你能说说他们是如何工作的吗?并给
  • ①async和await如何用异步实现同步写法的 ②为什么promise可以实现链式调用 ③手写实现promise的思路 ④如何去管理promise的状态 2.for each和map的区别 3.闭包 ①闭包的特点,有什么问题,可以用来做什么 4.原型链 ...
  • 漂亮的代码系列

    2018-04-09 17:59:00
    漂亮的代码系列 漂亮的代码1:计算器 亮的代码2:遍历文件夹目录,使用promise 漂亮的代码3:flatten 一...如何把函数都用promise方式实现? nodejs 代码设计模式1:同步函数变异步 转载于:https://www.cnblogs.c...
  • 迅雷前端一面

    2017-09-25 19:06:32
    原生js里面怎么操作cookie cors怎么让cookie传过去 怎么给cookie中添加值 跨域 jsonp是同步的?为什么不能传post请求,为...es6怎么实现 promise对象中抛出异常如何处理 对象深拷贝后,如何不继承原型上的东西
  • “异步的” setState 如何同步获取 state fetch拦截器的实现 js 异步发展史 手写源码系列 手写 Promise Promise asap curry 柯理化 debounce throttle ES5 array api forEach map filter reduce ...
  • 当我们想以同步的方式来处理异步任务时候就 microtask(比如我们需要直接在某段代码后就去执行某个任务,就像Promise一样)。 其他情况就直接 macrotask。 两者的具体实现 <ul><li>macrotasks...
  • 深入浅出 Koa 原理

    2021-01-08 14:41:42
    - promise 本文主要针对koa的原理进行讨论,属于深度篇,并不会对koa的使用过多介绍。 如果在阅读过程中,发现有哪些地方我写的不太清楚,不容易理解,希望能提出,我会参考...
  • 如何实现自己的Handler,比如按短短信计费 参考 CMPPChargingDemoTest 里的扩展位置 实体类说明 CMPP的连接端口 com.zx.sms.connect.manager.cmpp.CMPPEndpointEntity 表示一个Tcp连接的发起端,或者接收端。用来...
  • 除非库把强大的 autoprefixer 再实现一遍。 使用 className 可以很好的加上前缀,在追查文件时能得到清晰的定位,下面是我们对 CSS 命名空间的一种实现 ——html-path-loader css-path-loader 插件 ...
  • 精通AngularJS part1

    2016-10-10 15:32:02
    AngularJS如何判断依赖关系318 编写会被安全压缩的JavaScript代码319 数组风格依赖注入的缺陷322 模板预加载323 使用指令预加载模板324 填充$templateCache服务325 组合使用不同的预加载技术327 122优化首页...
  • 没有原生PromiseMO。 这充分说明了microtask才是nextTick的本质,MO什么的只是个备胎,要是有比MO优先级更高、浏览器兼容性更好的microtask,那可能就分分钟把MO拿下了。任何...
  • 第6章介绍库和API,讲解如何设计良好的API的技巧,以清楚、简洁和明确地表达程序,并提高可重用率。第7章讲解并发,在技术上讨论一些“约定成俗”的JavaScript用法。 Effective JavaScript:编写高质量JavaScript...
  • 小技巧: 如何更有效率的查看github上的文件 小伙伴可以下载一个插件叫做:Octotree,可以在左侧以树状的形式展示github中目录结构和文件列表,非常好用! 重要! PDF下载出错的小伙伴可以git clone整个项目即可!...
  • vue 是如何对数组方法进行变异的 ? 我们先来看看源码 <pre><code>js const arrayProto = Array.prototype; export const arrayMethods = Object.create(arrayProto); const methodsToPatch = [ "...
  • 延迟对象 延迟对象(Deferred Object,jQuery.Deferred对象)是一个可链接的(chainable)实用工具对象,实现Promise接口,可以在回调队列中注册多个回调、调用回调队列并转发任何同步/异步函数的成败状态。...
  • 包含 react/redux 服务端渲染、路由filter、websocket同步等。 可以猛戳 <a href="http://isomorphism-react-todomvc.coding.io/">DEMO</a> 地址。在控制台里能看到 <code>redux-logger</code> 中间件输出的 action ...
  • 枸杞的由来和技术栈

    2021-01-02 15:11:32
    可以 <code>react-native-interactable</code> 和 <code>lottie-react-native</code> 高效地实现复杂的动画,广受诟病的 <code>ListView</code> 也有了 <code><VirtualizedList></code> 、<code>...
  • 并且之前团队内也vue开发过一些项目</li></ul> 所以最终选择了Vue 选择vue周边依赖(全家桶) 框架定了Vue 后,接下来我需要挑选一些vue套餐来帮助开发,我挑选的套餐有: <ul><li>...
  • 就直接 ts 的 ThisType 来实现,否则就使用类型指定,将 this 指定为 Context。 而给 egg 对象中注入的方式就有点不是很优雅了,得一个一个方法来写,这个目前是还没想到什么好的办法&#...
  • 这里很显然代码都是同步的,但很多情况下我们的代码都是异步执行的,那么异步的代码要怎么测试呢? 比如这里<code>index.js的代码变成了一段异步代码: <pre><code> js 'use strict'...
  • vue所有基础语法部分 插值操作 Mustache <div id="app"> <...--mustache语法中,不仅仅可以直接写变量,也可以写简单的表达式-->...下面例子:当修改input框的值时,使用了v-once指令的p元素不会随之改变,...

空空如也

空空如也

1 2
收藏数 31
精华内容 12
关键字:

如何用promise实现同步