Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >JavaScript 异步编程

JavaScript 异步编程

作者头像
用户3045442
发布于 2020-07-31 02:27:39
发布于 2020-07-31 02:27:39
1.3K00
代码可运行
举报
文章被收录于专栏:Android研究院Android研究院
运行总次数:0
代码可运行

❝掌握JavaScript主流的异步任务处理 ( 本篇文章内容输出来源:《拉钩教育大前端训练营》参阅《你不知道的JavaScript中卷》异步章节)❞

JavaScrip 采用单线程模式工作的原因,需要进行DOM操作,如果多个线程同时修改DOM浏览器无法知道以哪个线程为主。

JavaScirpt分为:同步模式、异步模式

同步模式与异步模式

同步模式

同步模式其实就是:排队执行,下面根据一个Gif动画来演示同步模式,非常简单理解,js维护了一个正在执行的工作表,当工作表的任务被清空后就结束了。

如下打开调试模式,注意观察Call Stack调用栈的情况,当执行foo方法的是否foo会进入Call Stack调用栈之后打印'foo task',然后执行bar()方法bar进入调用栈打印'bar task',bar执行完后被移除调用栈,foo被移除调用栈然后打印'global end'执行结束。

1.gif

存在的问题:如果其中的某一个任务执行的时间过长,后面的任务就会被阻塞,界面就会被卡顿,所以就需要使用异步模式去执行避免界面被卡死。

异步模式

通过一个图来演示异步任务,用到事件循环与消息队列机制实现

Untitled 0.png

Promise异步方案

常见的异步方案就是通过回调函数来实现,导致回调地狱的问题,CommonJS社区提出了Promise方案并在ES6中采用了。如下代码实现一个环绕动画如果通过回调会嵌套多次。

案例演示地址

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
let box = document.querySelector('#box');
    move(box, 'left', 300, () => {
        move(box, 'top', 300, () => {
            move(box, 'left', 0, () => {
                move(box, 'top', 0, () => {
                    console.log('运动完成');
                });
            });
        });
    });

Promise 的使用案例演示代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//应用案例
function ajax(url) {
    return new Promise(function (resolve, reject) {
        var xhr = new XMLHttpRequest();
        xhr.open('GET', url);
        xhr.responseType = 'json';
        xhr.onload = function () {
            if (this.status === 200) {
                resolve(this.response);
            } else {
                reject(new Error(this.statusText));
            }
        }
        xhr.send();
    });
}

let promise2 = ajax('./api/user.json');
let newPromise = promise2.then((res) => {
    console.log(res);
});
console.log(promise2 === newPromise);//false 每一个then都返回一个新的promise对象
//then 仍然会导致回调地狱 尽量保证异步任务的扁平化

//也可以在then方法中返回一个promise对象
ajax('./api/user.json').then(res=>{
    console.log(111);
    return ajax('./api/user.json');
}).then(res=>{
    console.log(222);
    return 'foo';
}).then(res=>{
    console.log(res);
})

//OUT:
false
Array(2)
111
222
foo

Promise 链式调用注意一下几点

  • Promise对象的then方法会返回一个全新的Promise对象
  • 后面的then方法就是在为上一个then返回的Promise注册回调
  • 前面then方法中回调函数的返回值会作为后面then方法回调的参数
  • 如果回调中返回的是Promise,那后面then方法的回调会等待它的结束

Promise异常处理

Promise 执行过程中出现错误onRejected回调会执行,一般通过catch方法注册失败回调,跟在then方法第二个参数注册回调结果是一样的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const promise = new Promise(function (resolve, reject) {
    //只能调用两者中的一个 一旦设置了某个状态就不允许修改了
    // resolve(100);//成功
    reject(new Error('promise rejected'));//失败
});

promise.then(function (value) {
    console.log('resolved', value);
}, function (err) {
    console.log('rejected', err);
}).catch(err=>{
    console.log("catch",err);
});

console.log('end');

推荐使用catch方法作为错误的回调,不推荐使用then方法的第二个参数作为错误回调,原因如下:

当我们在收到正确的回调又返回一个Promise对象但是在执行过程中出现了错误,而这时无法收到错误回调的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ajax('./api/user.json').then(res=>{
    console.log('onresolved',res);
    return ajax('/error.json');
},err=>{
    console.log("onRejected",err);
});

我们再来看catch方法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ajax('./api/user.json').then(res=>{
    console.log('onresolved',res);
    return ajax('/error.json');
}).catch(err=>{
    console.log("onRejected",err);
});

打印结果如下:catch方法可以捕捉到then方法return的新的Promise对象的执行错误。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
onresolved (2) [{}, {}]
onRejected Error: Not Found
    at XMLHttpRequest.xhr.onload (promise.js:28)

除此之外全局对象注册unhandlerdrejection 事件,处理代码中没有被手动捕获处理的异常。下面是node中的方法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
process.on('unhandledRejection',(reason,promise)=>{
    //reason => Promise 失败原因,一般是一个错误对象
  //promise => 出现异常的Promise对象
})

一般不推荐使用,应该在代码中明确捕获每一个可能的异常,而不是丢给全局处理

Promise 的静态方法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//一个成功状态的Promise 对象
Promise.resolve('foo').then(res=>{
    console.log(res);
});
var promise = ajax('./api/user.json');

var promise2 = Promise.resolve(promise);//如果传入一个Prmose对象会原样返回相同的Promise对象

console.log(promise === promise2);//true

//如下传入的一个对象带有then方法的对象一样可以执行
Promise.resolve({
    then:function(onFulfilled,onRejected){
        onFulfilled('f00');
    }
}).then(res=>{
    console.log(res);//f00
});

//创建一个失败状态的Promise对象
Promise.reject(new Error('rejected')).catch(err=>{
    console.log(err);
})

Promise并行执行:all race 将多个Promise对象组合到一起

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var promise = Promise.all([ajax('./api/user.json'),ajax('./api/user.json')]);

promise.then(res=>{
    console.log(res);
})
//都成功才会成功 有一个失败就会返回失败状态回调
ajax('./api/user.json')
.then(res=>{
    const urls = Object.values(res);
    console.log('??',urls);
    const tasks = urls.map(url=>{
        console.log(url);
        return ajax(url);
    });
    console.log(tasks);
    return Promise.all(tasks);
}).then(res=>{
    console.log(res);
});

//race 只会等待第一个结束的任务
const request = ajax('./api/user.json');

const timeout = new Promise((resolve,reject)=>{
    setTimeout(() => {
        reject(new Error('timeout'));
    }, 500);
});

Promise.race([request,timeout]).then(res=>{
    console.log(res);
}).catch(err=>{
    console.log(err);    
});

模仿网络慢的情况,可以看到race会执行reject

Untitled 1.png

Promise 执行时序:宏任务与微任务

Promise的回调会作为微任务执行。微任务:提高整体的响应能力。目前大部分异步回调作为宏任务

常见的宏任务与微任务如下图所示:

Untitled 2.png

下面是JavaScript执行异步任务的执行时序图:

Untitled 3.png

看下面的例子来进行理解: 下列例子中输出: 2 4 1 3 5

这其实也符合了上图事件循环的原理,先主任务执行输出: 2 4 之后查询是否有微观任务没有就新建宏观任务执行

然后宏观任务执行输出:1 3

之后查询是否之后查询是否有微观任务没有就新建宏观任务执行

执行输出: 5

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
let time = 0;
    setTimeout(()=>{
        time = 1;
        console.log(time);
        //宏任务嵌套宏任务
        setTimeout(()=>{
            time = 5;
            console.log(time);
        },1000);
    },1000);
    time = 2;
    console.log(time);
    setTimeout(()=>{
        time=3;
        console.log(time);
    },1000);
    time = 4;
    console.log(time);

下面我们在看一个带有微任务的例子: 下面例子输出的结果: 2 4 6 1 3 5.主任务执行完毕之后先执行微任务.

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
let time = 0;
    setTimeout(()=>{
        time = 1;
        console.log(time);
        //宏任务嵌套宏任务
        setTimeout(()=>{
            time = 5;
            console.log(time);
        },1000);
    },1000);
    time = 2;
    console.log(time);
    setTimeout(()=>{
        time=3;
        console.log(time);
    },1000);
    time = 4;
    console.log(time);
    //微任务
    let observer = new MutationObserver(()=>{
        time = 6;
        console.log(6);
    });
    observer.observe(document.body,{
        attributes:true
    });
    document.body.setAttribute('kkb',Math.random());

Generator异步方案

首先需要连接一下迭代器的

「迭代器」

❝for...in : 以原始插入的顺序迭代对象的可枚举属性for...of : 根据迭代对象的迭代器具体实现迭代对象数据 可迭代对象 - 实现了[Symbol.iterator]方法数组结构有[Symbol.iterator]方法,但是如果要迭代Object就需要添加[Symbol.iterator]方法的实现如下代码: ❞

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
</body>
<script>
    //for of/ for in 迭代器
    //for...in : 以原始插入的顺序迭代对象的可枚举属性
    //for...of : 根据迭代对象的迭代器具体实现迭代对象数据 可迭代对象 - 实现了[Symbol.iterator]方法
    let arr = ['a','b','c','d'];
    let obj = {
        a:1,
        b:2,
        c:3
    }
    for(let attr in arr){
        console.log(attr);//0 1 2 3
    }
    for(let val of arr){
        console.log(val);//a b c d
    }
    console.dir(arr);//symbol(Symbol.iterator): ƒ values()
    console.dir(obj);//没有Symbol.iterator方法
    
    //如果要对象使用for of需要加一个属性 自定义迭代器
    obj[Symbol.iterator] = function(){
        //迭代协议
        //将对象value转换为数组
        let values = Object.values(obj);
        //将对象key转为数组
        let keys = Object.keys(obj);
        // let values = [...obj];
        console.log(values);
        let index = 0;
        //必须返回一个对象 同时必须有一个next方法
        return {
            next(){
                //done:表示循环是否完成
                //value:for a of obj a就是value
                //必须返回一个对象
                if (index >= values.length) {
                    return{
                        done:true
                    }
                }else{
                    return{
                        done:false,
                        value:{
                            key:keys[index],
                            value:obj[keys[index++]]
                        }
                    }
                }
            }
        }
    }
    //可以测试直接迭代方法
    let objIterator = obj[Symbol.iterator]();
    //执行next方法
    console.log(objIterator.next());
    
    //其实for...of 一直调用objIterator.next() 直到done:true就会停止
    for(let o of obj){
        //obj is not iterable
        console.log(o);
    }
</script>
</html>

❝Generator函数比普通函数多了一个*号,函数内部使用yield语句,定义遍历器的每个成员,即不同的内部状态. 实现可迭代的函数.Generator函数一般很少会使用了解即可. ❞

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
</body>
<script>
    /**
     * 定义可迭代函数 yield 每次迭代的返回值 
     */
    function* fn() {
        yield new Promise((resolve, reject) => {
            setTimeout(() => {
                console.log("a");
                resolve("1");
            }, 500);
        });
        yield new Promise((resolve, reject) => {
            setTimeout(() => {
                console.log("b");
                resolve("2");
            }, 500);
        });
        yield new Promise((resolve, reject) => {
            setTimeout(() => {
                console.log("c");
                resolve("3");
            }, 500);
        });
    }
    let f = fn();
    // console.log(f.next());
    // for (const iterator of f) {
    //     console.log(iterator);
    // }
    function co(fn) {
        let f = fn();
        next();
        function next(data){
            let result = f.next();
            console.log(result);
            if(!result.done){
                //上一个异步执行完毕
                result.value.then((info)=>{
                    console.log(info,data);
                    next(info);
                });
            }
        }
    }
    co(fn);
    // for (let fn of f) { 一同执行 不能异步调用
    // }
</script>
</html>

Generator 生成器函数的使用

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//Generator 生成器函数
function* foo() {
    try {
        console.log('start');
        const res = yield 'foo';
        console.log(res);
    } catch (e) {
        console.log(e);
    }

}

const generator = foo();

const result = generator.next();

console.log(result);

generator.next('bar');

generator.throw(new Error('Generator Error'));//抛出一个异常

Generator 异步使用的案例如下代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function* main() {
    try{
        const users = yield ajax('./api/user.json');
        console.log(users);
        const posts = yield ajax('./api/user.json');
        console.log(posts);
    }catch(e){
        console.log(e);
    }
}
//通用的异步生成器方法
function co(generator){
    const g = generator();
    function handleResult(result){
        if(result.done) return;
        result.value.then(data=>{
            handleResult(g.next(data));
        }).catch(err=>{
            g.throw(err);
        })
    }
    handleResult(g.next());
}

co(main);

Async/Await 语法糖

推荐使用异步编程的标准.需要注意await 后面必须是一个Promise对象,await只能出现在async函数内部目前还不支持(以后可能会支持)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
async function  main2() {
    try{
        const users = await ajax('./api/user.json');
        console.log(users);
        const posts = await ajax('./api/user.json');
        console.log(posts);
    }catch(e){
        console.log(e);
    }
}
main2();

Promise 源码手写实现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1. Promise 是一个类 在执行这个类的时候 需要传递一个执行器进去 这个执行器会立即执行
2. Promise 中有三种状态分别为:pending -> fulfilled pending->rejected
3. resolve reject 函数用来更改状态
    resolve:fulfilled
    reject:rejected
4. then方法内部做的事情就是判断状态 如果状态成功调用成功回调函数
如果状态失败就回调失败的回调函数
5. then成功或失败都有一个参数分别表示成功的值和失败的原因
6. 记录成功的值和失败的值
7. 处理执行器内部异步情况的处理 调用resolve或reject
8. 处理then方法可以被多次调用
9. then方法可以被链式调用 后面then方法回调函数拿到的值是上一个then方法
回调函数的返回值
10. then 返回值是普通值还是Promise对象
11. then 返回相同的Promise对象循环调用的判断
12. 执行器内部发生错误 回调给reject,then 内部发生错误的处理
13. then无参数的链式调用实现
14. all等静态方法实现
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制

const PENDING = 'pending';//等待
const FULFILLED = 'fulfilled';//成功
const REJECTED = 'rejected';//失败

class MyPromise {
    constructor(executor) {
        try {
            executor(this.resolve, this.reject);//执行器立即执行
        } catch (e) {
            this.reject(e);
        }
    }
    status = PENDING;//定义状态
    //成功之后的值
    value = undefined;
    //失败之后的值
    error = undefined;

    //成功回调
    onFulfilled = [];
    //失败回调
    onRejected = [];
    //箭头函数 this指向不会被更改 this还会指向MyPromise对象
    resolve = (value) => {
        //0 判断状态是不是pending 阻止向下执行
        if (this.status !== PENDING) {
            return;
        }

        //1 状态更改
        this.status = FULFILLED;
        //2 保存成功之后的值
        this.value = value;
        //3 成功回调是否存在
        // this.onFulfilled && this.onFulfilled(this.value);
        while (this.onFulfilled.length) {
            this.onFulfilled.shift()();
        }
    }
    reject = (error) => {
        //0 判断状态是不是pending 阻止向下执行
        if (this.status !== PENDING) {
            return;
        }
        //1 状态更改
        this.status = REJECTED;
        //2 保存失败之后的值
        this.error = error;
        //3 失败回调是否存在
        // this.onRejected && this.onRejected(this.error);
        while (this.onRejected.length) {
            this.onRejected.shift()();
        }
    }
    then(onFulfilled, onRejected) {
        onFulfilled = onFulfilled ? onFulfilled : value => value;
        onRejected = onRejected ? onRejected : error => { throw error };
        //1. 实现链式调用
        let p = new MyPromise((resolve, reject) => {
            if (this.status === FULFILLED) {
                setTimeout(() => {
                    try {
                        //拿到回调函数的返回值
                        let result = onFulfilled(this.value);
                        //传递给下一个Promise对象
                        //判断result是普通值还是Promise对象
                        //如果是普通值 直接调用resolve
                        //如果是promise对象 查看promise对象返回的结果
                        //再根据promise对象返回的结果 决定调用resolve还是reject
                        // resolve(result);
                        //需要等待同步代码执行完毕拿到p在执行
                        this.resolvePromise(p, result, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                }, 0);
            } else if (this.status == REJECTED) {
                setTimeout(() => {
                    try {
                        //拿到回调函数的返回值
                        let result = onRejected(this.error);
                        this.resolvePromise(p, result, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                }, 0);
            } else {
                //由于异步代码没有立即执行 先存储回调 等异步代码执行完成后再执行回调
                this.onFulfilled.push(() => {
                    setTimeout(() => {
                        try {
                            //拿到回调函数的返回值
                            let result = onFulfilled(this.value);
                            this.resolvePromise(p, result, resolve, reject);
                        } catch (e) {
                            reject(e);
                        }
                    }, 0);
                });
                this.onRejected.push(() => {
                    setTimeout(() => {
                        try {
                            //拿到回调函数的返回值
                            let result = onRejected(this.error);
                            this.resolvePromise(p, result, resolve, reject);
                        } catch (e) {
                            reject(e);
                        }
                    }, 0);
                });
            }
        });
        return p;
    }
    resolvePromise(p, result, resolve, reject) {
        if (p === result) {
            return reject(new TypeError('TypeError: Chaining cycle detected for'));
        }
        if (result instanceof MyPromise) {
            //Promise对象 把新的Promise对象的值传递下去
            result.then(resolve, reject);
        } else {
            //普通值
            resolve(result);
        }
    }
    static all(array) {
        let result = [];
        let index = 0;
        return new MyPromise((resolve, reject) => {
            function addData(key, value) {
                result[key] = value;
                index++;
                if (index === array.length) {
                    //需要等待异步操作完成再调用resolve
                    resolve(result);
                }
            }
            for (let i = 0; i < array.length; i++) {
                let cur = array[i];
                if (cur instanceof MyPromise) {
                    cur.then((value) => {
                        addData(i, value);
                    }, (err) => {
                        reject(err);
                    });
                } else {
                    addData(i, cur);
                }
            }
        });
    }
    static resolve(value) {
        if (value instanceof MyPromise) {
            return value;
        }
        return new MyPromise((resolve, reject) => {
            resolve(value);
        });
    }
    static reject(error){
        return new MyPromise((resolve,reject)=>{
            reject(error);
        })
    }
    finally(callback){
        return this.then(res=>{
            return MyPromise.resolve(callback()).then(()=>res);
        },err=>{
            return MyPromise.resolve(callback()).then(()=>{throw err});
        });
    }
    catch(error){
        return this.then(undefined,error);
    }
}

//
module.exports = MyPromise;
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-07-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Android研究院 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
ES6笔记(7)-- Promise异步编程
Promise是一种异步编程的解决方案,本质来说其实它是一种规范,Promises/A+规范
书童小二
2018/09/03
6920
ES6笔记(7)-- Promise异步编程
如何写出一个惊艳面试官的 Promise【近 1W字】 前言源码1.Promise2.Generator3.async 和 await4.Pro
1.高级 WEB 面试会让你手写一个Promise,Generator 的 PolyFill(一段代码); 2.在写之前我们简单回顾下他们的作用; 3.手写模块见PolyFill.
火狼1
2020/05/09
7520
如何写出一个惊艳面试官的 Promise【近 1W字】
                            前言源码1.Promise2.Generator3.async 和 await4.Pro
手写Promise完整介绍
Promise是一种用于处理异步操作的机制,它可以将异步操作的结果以同步的方式进行处理和返回。在JavaScript中,Promise是一种内置对象,但我们也可以手动实现一个Promise类来更好地理解其原理和工作方式。
can4hou6joeng4
2023/11/16
5360
前端二面手写面试题总结
then 方法返回一个新的 promise 实例,为了在 promise 状态发生变化时(resolve / reject 被调用时)再执行 then 里的函数,我们使用一个 callbacks 数组先把传给then的函数暂存起来,等状态改变时再调用。
helloworld1024
2022/10/27
8760
京东前端高频面试题合集
现代计算机中数据都是以二进制的形式存储的,即0、1两种状态,计算机对二进制数据进行的运算加减乘除等都是叫位运算,即将符号位共同参与运算的运算。
yyzzabc123
2022/09/13
5610
从零开始写一个符合Promises/A+规范的promise
Promise 是异步编程的一种解决方案,比传统的解决方案回调函数和事件更合理更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。本篇不注重讲解promise的用法,关于用法,可以看阮一峰老师的ECMAScript 6系列里面的Promise部分:
Nealyang
2019/09/29
1.6K0
从零开始写一个符合Promises/A+规范的promise
看了就会,手写Promise原理,最通俗易懂的版本!!!
大家好,我是林三心,相信大家在日常开发中都用过Promise,我一直有个梦想,就是以最通俗的话,讲最复杂的知识,所以我把通俗易懂放在了首位,今天就带大家手写实现以下Promise吧,相信大家一看就懂。
用户6256742
2024/05/17
8420
看了就会,手写Promise原理,最通俗易懂的版本!!!
从零开始实现一个Promise
众所周知,Promise是ES6引入的新特性,旨在解决回调地狱。下面是一个简单的例子:控制接口调用顺序:
helloworld1024
2022/10/14
2000
社招前端经典手写面试题合集
使用时间戳的节流函数会在第一次触发事件时立即执行,以后每过 wait 秒之后才执行一次,并且最后一次触发事件不会被执行
helloworld1024
2022/10/19
8060
【吐血整理】前端JavaScript高频手写面试大全,助你查漏补缺
https://segmentfault.com/a/1190000038910420
@超人
2021/02/26
9070
【吐血整理】前端JavaScript高频手写面试大全,助你查漏补缺
异步发展流程-手摸手带你实现一个Promise
首先介绍一下高阶函数,即一个函数的参数是函数或者函数返回值为函数,此函数称做高阶函数。
Careteen
2022/02/14
1K0
JavaScript异步编程
#前言 从我们一开始学习JavaScript的时候就听到过一段话:JS是单线程的,天生异步,适合IO密集型,不适合CPU密集型。但是,多数JavaScript开发者从来没有认真思考过自己程序中的异步到底是怎么出现的,以及为什么会出现,也没有探索过处理异步的其他方法。到目前为止,还有很多人坚持认为回调函数就完全够用了。
leocoder
2018/10/31
1.2K0
20道前端高频面试题(附答案)_2023-02-27
最简单的Promise实现有7个主要属性, state(状态), value(成功返回值), reason(错误信息), resolve方法, reject方法, then方法
gogo2027
2023/02/27
9890
一杯喜茶的时间手搓Promise
我们都知道,JS是单线程的,只有前一个任务结束,才能执行下一个任务。显然在浏览器上,这样执行会堵塞浏览器对DOM的渲染。所以,JS中会有很多异步操作,那JS是如何实现异步操作呢?这就要想到「Promise对象」了,文本先来认识Promise,再手写代码实现Promise。
JowayYoung
2020/04/01
8280
前端异步代码解决方案实践(二)
早前有针对 Promise 的语法写过博文,不过仅限入门级别,浅尝辄止食而无味。后面一直想写 Promise 实现,碍于理解程度有限,多次下笔未能满意。一拖再拖,时至今日。
前朝楚水
2018/07/26
3.4K0
JavaScript的异步编程之Promise
一种更优的异步编程统一 方法,如果直接使用传统的回调函数去完成复杂操作就会形成回调深渊
开水泡饭
2022/12/26
7380
JavaScript的异步编程之Promise
手写系列-这一次,彻底搞懂 Promise
想要实现 Promise,必须先了解 Promise 是什么,以及 Promise 有哪些功能。
游魂
2023/10/17
4410
手写系列-这一次,彻底搞懂 Promise
JavaScript异步编程
平时开发经常会用到js异步编程,由于前端展示页面都是基于网络机顶盒(IPTV的一般性能不太好,OTT较好),目前公司主要采取的异步编程的方式有setTimeout、setInterval、requestAnimationFrame、ajax,为什么会用到异步呢,就拿业务来说,若前端全部采取同步的方式,那加载图片、生成dom、网络数据请求都会大大增加页面渲染时长。
Jack Chen
2018/09/14
9640
JavaScript异步编程
原生JS灵魂之问(下), 冲刺进阶最后一公里(附个人成长经验分享)
笔者最近在对原生JS的知识做系统梳理,因为我觉得JS作为前端工程师的根本技术,学再多遍都不为过。打算来做一个系列,一共分三次发,以一系列的问题为驱动,当然也会有追问和扩展,内容系统且完整,对初中级选手会有很好的提升,高级选手也会得到复习和巩固。这是本系列的第三篇。
用户4131414
2020/03/19
2.1K0
Javascript之我也来手写一下Promise
  Promise太重要了,可以说是改变了JavaScript开发体验重要内容之一。而Promise也可以说是现代Javascript中极为重要的核心概念,所以理解Promise/A+规范,理解Promise的实现,手写Promise就显得格外重要。如果要聊Promise就要从回调函数聊到回调地狱,再聊到同步异步,最终聊到Promise、async await。但是我们这篇文章,目的是手写Promise,这些前置知识如果大家不了解的话,希望可以去补充一下。那你可能会说了,我他妈不懂你在说啥,我就是想手写Promise,不行么?大佬~~那肯定是没问题的。好了,废话不多说,咱们开始吧。
zaking
2022/09/09
8820
推荐阅读
相关推荐
ES6笔记(7)-- Promise异步编程
更多 >
LV.3
这个人很懒,什么都没有留下~
交个朋友
加入腾讯云官网粉丝站
蹲全网底价单品 享第一手活动信息
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档