Promise浅析(一)——基础篇

之前在慕课网上学习nodejs时接触到了promise这个东东,感觉还不错,于是就想系统的学习一下。但很快就发现网上关于promise的资料有点少,于是就萌生了写有关promise的系列博客的想法。由于这个系列的博客我也是边学边写,难免会出现纰漏,所以有误的地方还请大家多多指正。
基础篇主要介绍什么是promise、promise的基本API。下面就进入正题。

一、与Promise相关的概念
1.什么是Promise/Promise有什么用
首先来看定义——Promise是js针对异步场景的解决方案,它可以以同步的方式编写代码,执行的操作却是异步的。
举个栗子,假如我们要实现一个动画——有三个小球,分别为红色、黄色、绿色,最后展示的效果是绿球先移动一段距离,结束移动后黄球移动,黄球移动结束后红球移动,红球移动一段距离后再移回原位,红球归位后黄球移动归位,黄球移动归位后绿球移动归位,在黄球归位以后动画结束。
不知道在看完整个动画的流程以后,大家对该动画的实现有什么想法,下面分享一下我的代码。首先是html部分

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>promise animation</title>
    <link rel="stylesheet" type="text/css" href="ball.css">
</head>
<body>
     <div id="balla" class="ball" style="left:0"></div>
     <div id="ballb" class="ball" style="left:50px"></div>
     <div id="ballc" class="ball" style="left:100px"></div>

      <!-- <script type="text/javascript" src="bluebird.min.js"></script> -->
      <script type="text/javascript" src="ball.js"></script>
</body>
</html>

这里大家需要在下方引入bluebird库的部分。目前的实例还不需要用到promise库。但由于Promise是ES6中引入的概念,为了防止某些运行环境不支持promise,我们采用bluebird库进行实现。之后的例子会详细介绍如何获得及使用bluebird库。
那么,首先如何获取bluebird库呢?我是用npm来获取的。在node.js运行环境中,输入npm install bluebird -g来获取bluebird库,运行完成之后的bluebird库目录结构如下所示
这里写图片描述
进入到js文件夹,我们会看到
这里写图片描述
有browser与release两个文件夹,browser文件夹中放置的是在浏览器端使用的bluebird库,就类似于jQuery,打开该文件夹,我们可以看到
这里写图片描述
接下来就可以把想要使用的库文件拷贝到相应位置进行引用。
下面来看一下css代码

*{margin:0;padding:0;}
.ball{
    position:absolute;
    width:40px;
    height:40px;
    border-radius:20px;
}
#balla{
    background-color: red;
}
#ballb{
    background-color: yellow;
}
#ballc{
    background-color: green;
}

最后显示在浏览器的样子就是这样子的
这里写图片描述
那么,如果用原始的回调的方式进行编写,代码就应该想这样子

var balla=document.querySelector("#balla");
var ballb=document.querySelector("#ballb");
var ballc=document.querySelector("#ballc");

//ball传入小球的id,distance为移动的距离
function animateBall(ball,distance,callback){
    setTimeout(function(){
        //获取当前小球的位置
        var position=parseInt(ball.style.left,10);
        if(position==distance){
            callback();
        }else if(position<distance){
            position++;
            ball.style.left=position+"px";
            animateBall(ball,distance,callback);
        }else if(position>distance){
            position--;
            ball.style.left=position+"px";
            animateBall(ball,distance,callback);
        }
    },13);
    //13毫秒每帧
}

animateBall(ballc,500,function(){
    animateBall(ballb,450,function(){
        animateBall(balla,400,function(){
            animateBall(balla,0,function(){
                animateBall(ballb,50,function(){
                    animateBall(ballc,100,function(){
                    });
                });
            });
        });
    });
});

我们可以看到,在最后的回调部分,噼里啪啦的写了好几行,目前的需求写起来还算比较简单,但如果回调相当之多肿么办?这样子嵌套着写也不方便日后的维护,而且回调函数真正的问题在于它剥夺了我们使用 return 和 throw 这些关键字的能力,顺便也剥夺了我们使用链式编程的权力。于是乎,js便引入了promise来解决这个问题。

2.Promise构造函数
<1>promise构造函数接受一个函数作为参数,该函数包含两个参数,分别是resolve方法与reject方法

var promise=window.Promise;//获取全局promise对象
function promiseAnimate(ball,distance){
    return new promise(function(resolve,reject){
        function _animateBall(){
            setTimeout(function(){
                var position=parseInt(ball.style.left,10);
                if(distance<0){
                    reject(new Error("距离不能为负数"));
                }else if(position==distance){
                    resolve("完成移动");
                }else if(position<distance){
                    position++;
                    ball.style.left=position+"px";
                    _animateBall();
                }else if(position>distance){
                    position--;
                    ball.style.left=position+"px";
                    _animateBall();
                }
            },13);
        };
        _animateBall();
    });
}

在分析代码之前,我们需要了解promise的特点
<2>promise的特点
promise对象有三种状态,分别为“未完成”(pending)、“已完成”(fullilled或者叫做resolved)、“失败”(rejected)。
只有异步操作的结果可以决定当前是哪一种状态。
一旦状态改变,就不会再变,任何时候都可以得到这个结果,并且状态只可能从pending变为resolved,或者从pending变为rejected
<3>构造函数分析
如果异步操作成功,则用resolve方法把promise对象的状态从pending转为resolved;如果失败,则从pending转为rejected。

下面是用最简单的promise进行编写。由于本节只简单介绍一下promise,所以还没有展示如何获取并处理错误。这些将在下一篇博客中为大家详细讲解。

promiseAnimate(ballc,500).then(function(){
    return promiseAnimate(ballb,450)
}).then(function(){
    return promiseAnimate(balla,400)
}).then(function(){
    return promiseAnimate(balla,0)
}).then(function(){
    return promiseAnimate(ballb,50)
}).then(function(){
    return promiseAnimate(ballc,100)
}).then(function(value){
    console.log(value)
    /*前面的每个.then方法中函数的参数都可以是value,并且也可以console出来“完成移动”*/
});

二、基本API
promise对象的基本API有:
promise.resolve()、promise.reject()、promise.prototype.then()、promise.prototype.catch()、promise.all()

到此为止,我们的promise浅析的第一部分就结束了,下一章将讲解promise基本API的使用。敬请期待。最后为大家分享一下promise系列博客主要参考的网站http://liubin.org/promises-book/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在JavaScript中,可以使用Promise的`then()`方法来等待上一个Promise完成后再执行下一个Promise。 当一个Promise被解决(fulfilled)时,它会调用它的`then()`方法,该方法接受两个参数:一个是成功回调函数,另一个是失败回调函数。成功回调函数将在Promise成功时被调用,而失败回调函数将在Promise失败时被调用。 通过在`then()`方法中返回另一个Promise对象,可以实现等待上一个Promise完成后再执行下一个Promise。这种方式称为Promise链。 以下是一个示例代码,展示了如何通过Promise链来等待上一个Promise完成后再执行下一个Promise: ```javascript // 第一个Promise const firstPromise = new Promise((resolve, reject) => { setTimeout(() => { resolve('First Promise Resolved'); }, 1000); }); // 第二个Promise const secondPromise = new Promise((resolve, reject) => { setTimeout(() => { resolve('Second Promise Resolved'); }, 2000); }); // 等待第一个Promise完成后执行第二个Promise firstPromise.then((result) => { console.log(result); // 输出:First Promise Resolved return secondPromise; }).then((result) => { console.log(result); // 输出:Second Promise Resolved }); ``` 在上面的代码中,第一个Promise在1秒后被解决,然后第二个Promise在第一个Promise完成后的2秒后被解决。通过使用`then()`方法并返回下一个Promise对象,我们可以确保第二个Promise在第一个Promise完成后才会执行。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值