promise规范

Published: by Creative Commons Licence

为什么会有promise规范

js处理异步一般都是用callback,但一旦涉及串联的异步请求,就会多层callback嵌套,导致代码的可读性很差,维护起来也是非常费劲。Promise规范的提出,可以说完全改变了 js异步编程的写法,让异步编程变得十分容易理解。

promise规范实例

var p1 = new Promise(function(resolve, reject) {
	setTimeout(function() {
  		resolve("Success!");
	}, 1500);
});

p1.then(function(value) {
  console.log(value); // Success!
});

1.5s后控制台打印Success!

好了,我们先来认识一下 Promise/A+ 规范:

  • 一个promise对象有三种状态:等待(pending),已完成(fullfilled),已拒绝(rejected)
  • 一个promise对象的状态只能从 pending 转到 fullfilled或者rejected,不能逆向转换,并且fullfilled和rejected之间不能相关转换
  • promise必须实现then方法,并且then必须返回一个promise,同一个promise可以连续调用then方法,执行的顺序与调用的顺序一致
  • then方法有两个参数,第一个参数是成功时的回调(promise的状态从pending变成fullfilled时调用),第二个参数是失败时的回调(promise的状态从pending变成rejected时调用)。如果这两个回调返回了一个值x,如果x也是一个promise,那么x的状态将会被采用,简单点说如下:var promise2 = promise1.then(onFullfilled, onRejected);如果onFullfilled或者onRejected返回的值x也是一个promise对象,那么promise2的状态将采用x的状态,当x的状态是pending时,promise2的状态也是pending,当x的状态变成fullfilled,那么promise2的状态也变成fullfilled,同时value与x的value一致。

实例

现在需要实现一个功能:抓取最新的一篇文章的作者的邮箱

流程就是:抓文章列表->抓文章資訊->抓作者

使用promise后,代码如下:

getArticleList().then(function(articles){
    return getArticle(articles[0].id);
}).then(function(article){
    return getAuthor(article.authorId);
}).then(function(author){
    alert(author.email);
});

function getAuthor(id){
    return new Promise(function(resolve, reject){
        $.ajax("http://beta.json-generator.com/api/json/get/E105pDLh",{
            author: id
        }).done(function(result){
            resolve(result);
        })
    });
}

function getArticle(id){
    return new Promise(function(resolve, reject){
        $.ajax("http://beta.json-generator.com/api/json/get/EkI02vUn",{
            id: id
        }).done(function(result){
            resolve(result);
        })
    });
}

function getArticleList(){
    return new Promise(function(resolve, reject){
       $.ajax(
        "http://beta.json-generator.com/api/json/get/Ey8JqwIh")
        .done(function(result){
            resolve(result);
        }); 
    });
}