es6-目前最好的异步解决方案Promise

前言

Promise是es6中的一个新的函数。它是为了解决js中异步操作导致的一些问题。

异步

异步一般是指需要等待的操作,比如读取一个文件,发起一个请求等待。异步一般伴随着回调函数。这种异步回调的设计,大大增加了js的运行速度,但是写起来有时候会很蛋疼。比如(回调地狱):

1
2
3
4
5
6
7
8
9
10
11
12
$.get("url1",function(data1){

$.get("url2",function(data2){

$.get("url3",function(data3){

$.get("url4",function(data4){
...
})
})
})
})

这样的代码,看起来一点都不优雅。于是ECMA组织设计了Promise的用法。

Promise

Promise是一个构造函数。所以需要new出实例。new Promise的时候,ECMA要求必须传入一个函数当做参数,且这个函数接收两个值,resolve、reject两个函数参数。。其中:

  • Resolve 成功函数
  • Reject 失败函数

Promise有以下特点:

  • 1)Promise对象不能单独使用,必须封装在一个函数中作为return值使用。后面的loadfile()函数就返回Promise对象的实例。
  • 2)只要函数return 了Promise对象的实例了,此时就能调用then,then中有两个参数,分别是表示成功回调和失败回调。
  • 3)New Promise而定时候,形参resolve和reject函数,分别表示成功、失败调用时then中那两个函数。
  • 4)往死记住,return new Promise 对象里面的那个函数,必须是异步的函数。
    例如以下代码:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    var fs  =require("fs");
    function loadfile(path){
    return new Promise((resolve,reject)=>{
    fs.readFile(path,(err,data)=>{
    if(err){
    reject();
    return;
    }
    resolve(data.toString());
    })
    })
    }


    loadfile("./txt/1.txt").then(function(data){
    console.log(data);
    return loadfile("./txt/2.txt")
    }).then(function(data){
    console.log(data);
    return loadfile("./txt/3.txt")
    }).then(function(data){
    console.log(data);
    })

可以看到回调函数的代码,已经变成了这种“队列”形式的代码。

ES7中的async/await 用同步的方式写异步

Es7中提出的async/await。。上面的代码解决了回调黑洞,但是then了好多次不好看。
现在的程序员提出了async/await这种写法,不写then().
用同步的方法,写异步函数。 比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var fs  =require("fs");
function loadfile(path){
return new Promise((resolve,reject)=>{
fs.readFile(path,(err,data)=>{
if(err){
reject();
return;
}
resolve(data.toString());
})
})
}
const work = async function(){
var data1 = await loadfile("./txt/1.txt");
console.log(data1);
var data2 = await loadfile("./txt/2.txt");
console.log(data2);
var data3 = await loadfile("./txt/3.txt");
console.log(data3);
}

work();

上面的代码会依次输出 data1,data2,data3里面的内容。
这种写法有以下特点:

  • async 必须出现在function标识符之前,表示这里面有await语句。说明是一个异步的语句
  • Await必须出现在async标记过的函数里面,表示“等待”。
  • Await必须添加在那个返回Promise对象的函数之前。

参考

Promise 对象