资讯专栏INFORMATION COLUMN

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

levius / 3215人阅读

摘要:回调函数回调函数是将一个函数作为参数,传递给另一个函数,然后在外部函数中调用该函数来完成某种例程或动作。案例源码回调函数处理都是基于的发展利用方法自动迭代

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

引言:

前端开发中,异步处理必不可少;
过去,我们经常用回调函数来完成异步处理,因此也经常产生回调地狱(callback hell);
今天,我们用实例来对比异步处理的方法;
是时候用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来处理我们的异步操作了。
案例源码:




    
    
    
    Document
    



    

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/93442.html

相关文章

  • [前端工坊]浅谈Web编程中异步调用发展演变

    摘要:三即生成器,它是生成器函数返回的一个对象,是中提供的一种异步编程解决方案而生成器函数有两个特征,一是函数名前带星号,二是内部执行语句前有关键字调用一个生成器函数并不会马上执行它里面的语句,而是返回一个这个生成器的迭代器对象。 文章来自微信公众号:前端工坊(fe_workshop),不定期更新有趣、好玩的前端相关原创技术文章。 如果喜欢,请关注公众号:前端工坊版权归微信公众号所有,转载请...

    qpwoeiru96 评论0 收藏0
  • 《Node.js设计模式》基于ES2015+回调控制流

    摘要:以下展示它是如何工作的函数使用构造函数创建一个新的对象,并立即将其返回给调用者。在传递给构造函数的函数中,我们确保传递给,这是一个特殊的回调函数。 本系列文章为《Node.js Design Patterns Second Edition》的原文翻译和读书笔记,在GitHub连载更新,同步翻译版链接。 欢迎关注我的专栏,之后的博文将在专栏同步: Encounter的掘金专栏 知乎专栏...

    LiuRhoRamen 评论0 收藏0
  • js学习之异步处理

    摘要:学习开发,无论是前端开发还是都避免不了要接触异步编程这个问题就和其它大多数以多线程同步为主的编程语言不同的主要设计是单线程异步模型。由于异步编程可以实现非阻塞的调用效果,引入异步编程自然就是顺理成章的事情了。 学习js开发,无论是前端开发还是node.js,都避免不了要接触异步编程这个问题,就和其它大多数以多线程同步为主的编程语言不同,js的主要设计是单线程异步模型。正因为js天生的与...

    VioletJack 评论0 收藏0
  • ES6-7

    摘要:的翻译文档由的维护很多人说,阮老师已经有一本关于的书了入门,觉得看看这本书就足够了。前端的异步解决方案之和异步编程模式在前端开发过程中,显得越来越重要。为了让编程更美好,我们就需要引入来降低异步编程的复杂性。 JavaScript Promise 迷你书(中文版) 超详细介绍promise的gitbook,看完再不会promise...... 本书的目的是以目前还在制定中的ECMASc...

    mudiyouyou 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<