JavaScript:从Callback到Async的发展过程——实例演示

发布时间:2019-08-15 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了JavaScript:从Callback到Async的发展过程——实例演示脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

阅读时间:12 minutes
文章类型:理论知识 & 案例演示
案例需求:用JavaScript实现,3个小球先后运动,完成接力赛跑
案例码:见文章最后

引言:

前端开发中,异步处理必不可少;
过去,我们经常用回调函数来完成异步处理,因此也经常产生回调地狱(callback hell);
今天,我们用实例来对比异步处理的方法;
是时候用async来处理我们的异步流程了。

JavaScript:从Callback到Async的发展过程——实例演示


Step 1: 回调函数 Callback

回调函数: 是将一个函数作为参数,传递给另一个函数,然后在外部函数中调用该函数来完成某种例程或动作。

用法:在函数内部调用函数

2. 用callback实现小球移动的方法;

function move(ele, target, callback) {
    let left = parseint(getComputedStyle(ele)["left"]);
    let timer = setInterval(function () {
        if (left >= target) {
            clearInterval(timer);
            callback();
        } else {
            left += 2;
            ele.style.left = left + "px";
        }
    }, 4)
}

2. 执行运动;

move(ball1, 200, function () { 
    move(ball2, 400, function () {
        move(ball3, 600, function () {
            alert("callback");
        });
    })
})

Step 2: Promise对象Promise

Promise: 是一个返回值的代理,它允许您将处理程序与异步操作的最终成功值或失败原因相关联。 这使异步方法可以像同步方法那样返回值:不是立即返回最终值,而是异步方法返回一个Promise,以便在未来的某个时间点提供该值。

用法:Promise 对象是由关键字 new 及其构造函数来创建的。该函数接收一个函数(executor function)作为它的参数。这个函数接受两个函数——resolvereject ——作为其参数。当异步任务顺利完成且返回结果值时,会调用 resolve 函数;而当异步任务失败且返回失败原因(通常是一个错误对象)时,会调用reject 函数。

1. 用PRomise实现小球移动的方法;

// 让move方法拥有Promise功能

function move(ele, target) { 
    return new Promise(function (resolve, reject) {
        let left = parseInt(getComputedStyle(ele)["left"]);
        let timer = setInterval(function () {
            if (left >= target) { 
                clearInterval(timer); 
                resolve(); 
            } else { 
                left += 2; 
                ele.style.left = left + "px"; 
            }
        }, 4)
    })
}

2. 执行运动,调用Promise.then()方法;

move(ball1, 200).then(function () {
    return move(ball2, 400);
}).then(function () {
    return move(ball3, 600);
}).then(function () {
    alert("promise");
})

Step 3: Generator对象 Generator

Generator:生成器函数在函数执行时能暂停,还能从暂停处继续执行,相当于将函数分段执行。

用法:必须用.next()配合 yield关键字使用;例如:

function *gen(){
yield 10;
y=yield 'foo';
yield y;
}
VAR gen_obj=gen();
console.LOG(gen_obj.next());    // 执行 yield 10,返回 10
console.log(gen_obj.next());    // 执行 yield 'foo',返回 'foo'
console.log(gen_obj.next(10));  // 将 10 赋给上一条 yield 'foo' 的左值,即执行 y=10,返回 10
console.log(gen_obj.next());    // 执行完毕,value 为 undefined,done 为 true   

1. 用Genertor实现小球移动的方法;

// 函数move方法调用上面Promise中的move方法;
function move(ele, target) { 
    return new Promise(function (resolve, reject) {
        let left = parseInt(getComputedStyle(ele)["left"]);
        let timer = setInterval(function () {
            if (left >= target) { 
                clearInterval(timer); 
                resolve(); 
            } else { 
                left += 2; 
                ele.style.left = left + "px"; 
            }
        }, 4)
    })
}

2. 执行运动,需要分布执行,但此方法需要手动分行执行;

let g = m();
g.next(); //让第一个小球运动;
g.next(); //让第二个小球运动;
g.next(); //让第三个小球运动;

3. 使用co库迭代generator执行器;

function co(it) {
    return new Promise(function (resolve, reject) {
        function next(d) {
            let { value, done } = it.next(d);
            if (!done) {
                value.then(function (data) {
                    next(data)
                }, reject)
            } else {
                resolve(value);
            }
        };
        next();
    });
}
// 一行代码实现函数执行,但是需要引入co库;
co(m()).then(function () {
    alert("generator");
})

Step 4: async/await函数 async/await

async: 异步函数声明定义了一个异步函数,它返回一个AsynCFunction对象。当async函数执行,返回一个Promise对象;

用法:用async声明函数,函数内配合await使用。

1. 用 async/await实现小球移动的方法;

// 调用上面的move()方法;
function move(ele, target) { 
    return new Promise(function (resolve, reject) {
        let left = parseInt(getComputedStyle(ele)["left"]);
        let timer = setInterval(function () {
            if (left >= target) { 
                clearInterval(timer); 
                resolve(); 
            } else { 
                left += 2; 
                ele.style.left = left + "px"; 
            }
        }, 4)
    })
}

2. 执行运动,函数内await方法;

async function a() {
    await move(ball1, 200);
    await move(ball2, 400);
    await move(ball3, 600);
}
a().then(function () {
    alert("async")
})

结语:

通过上述4种方法的对比,我们可以看出JavaScript这门语言的发展和进步;
ES6+增加了很多实用功能和方法,将有助于前期代码的编写以及后期代码的维护,是时候用 async/await来处理我们的异步操作了。

案例源码:
<!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=@R_360_2407@">
    <title>Document</title>
    <style>
        .container .ball {
            width: 100px;
            height: 100px;
            border-radius: 50%;
            position: absolute;
        }

        .container .ball:nth-child(1) {
            background-color: blue;
            left: 0;
            top: 20px;
        }

        .container .ball:nth-child(2) {
            background-color: yellow;
            left: 200px;
            top: 150px;
        }

        .container .ball:nth-child(3) {
            background-color: green;
            left: 400px;
            top: 280px;
        }
    </style>
</head>

<body>
    <div class="container">
        <div class="ball"></div>
        <div class="ball"></div>
        <div class="ball"></div>
    </div>
    <!-- <script src="Promise.js"></script> -->
    <script>
        let ball = document.querySelectorAll(".ball");
        let [ball1, ball2, ball3] = [...ball];

        // 1.回调函数处理;
        function move(ele, target, callback) {
            let left = parseInt(getComputedStyle(ele)["left"]);
            let timer = setInterval(function () {
                if (left >= target) {
                    clearInterval(timer);
                    callback();
                } else {
                    left += 2;
                    ele.style.left = left + "px";
                }

            }, 4)
        }
        move(ball1, 200, function () {
            move(ball2, 400, function () {
                move(ball3, 600, function () {
                    alert("callback");
                });
            })
        })

        // 2.promise
        // generator、async都是基于promise的发展;
        // function move(ele, target) {
        //     return new Promise(function (resolve, reject) {
        //         let left = parseInt(getComputedStyle(ele)["left"]);
        //         let timer = setInterval(function () {
        //             if (left >= target) {
        //                 clearInterval(timer);
        //                 resolve();
        //             } else {
        //                 left += 2;
        //                 ele.style.left = left + "px";
        //             }
        //         }, 4)
        //     })
        // }
        // move(ball1, 200).then(function () {
        //     return move(ball2, 400);
        // }).then(function () {
        //     return move(ball3, 600);
        // }).then(function () {
        //     alert("promise");
        // })

        // 3.Generator
        // function* m() {
        //     yield move(ball1, 200);
        //     yield move(ball2, 400);
        //     yield move(ball3, 600);
        // }
        // // 利用co方法自动迭代generator
        // function co(it) {
        //     return new Promise(function (resolve, reject) {
        //         function next(d) {
        //             let { value, done } = it.next(d);
        //             if (!done) {
        //                 value.then(function (data) { // 2,txt
        //                     next(data)
        //                 }, reject)
        //             } else {
        //                 resolve(value);
        //             }
        //         }
        //         next();
        //     });
        // }
        // co(m()).then(function () {
        //     alert("generator");
        // })

        // 4.async/await
        // async function a() {
        //     await move(ball1, 200);
        //     await move(ball2, 400);
        //     await move(ball3, 600);
        // }
        // a().then(function () {
        //     alert("async")
        // })
    </script>
</body>

</html>

脚本宝典总结

以上是脚本宝典为你收集整理的JavaScript:从Callback到Async的发展过程——实例演示全部内容,希望文章能够帮你解决JavaScript:从Callback到Async的发展过程——实例演示所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。