[JavaScript]Promise:异步编程

某项目的需求:先要请求API1,再以API1的结果请求API2.

var n, a;
//var r = window.md5;
var r =  function (password, username) {
        return new Promise((resolve, reject) => {    
                // 校验 获得 salt
                var saltUrl = "/wydaas/gateUser/noCheck/inner-user/salt.json"; // http://xx.yy.zz.kk:8080/wydaas/gateUser/noCheck/inner-user/salt.json
                var postData = { userName: username };
                //saltUrl += "?userName="+username;
                //var postData = null;
                console.log(postData);
                t.$http.post(saltUrl, postData).then((function(e) {
                        var n = e.data.data;
                        console.log("e:");
                        console.log(e);
                        var salt = e.body.data.data; // response 的 js json 对象
                        var text = password+"{"+salt+"}";
                        console.log(text);
                        console.log(sha256_digest(text));
                        resolve(sha256_digest(text));
                        /*
                        var n = e.data.data;
                        n.status ? (t.$message({
                                type: "success",
                                message: n.message || t.i18n.message.OPERATION_COMPLETE
                        }),
                        t.loginData.show = !1,
                        t.setCookieFun(),
                        t.$router.replace({
                                path: "/catalog"
                        }),
                        window.location.reload()) : (t.$alert(n.message || t.i18n.message.OPERATION_ERROR, t.i18n.message.SYSTEM_TXT, {
                                closeOnClickModal: !1,
                                confirmButtonText: t.i18n.message.OK,
                                type: "error"
                        }),
                        t.delCookie("accountInfo")),
                        t.saveLoading = !1 */
                }
                )).catch((function(e) {
                        this.saveLoading = !1;
                        reject(e);
                }
                ))
        })
};


"0" === t.loginType && (
        r(t.formData.userPassword, t.formData.userName).then(res => {
                console.log("res:" + res);
                n = "/wydaas/gateUser/noCheck/loginInner.json",
                a = {
                        userName: t.formData.userName,
                        //pwd: r(t.formData.userPassword, t.formData.userName)
                        pwd: res
                },
                
                console.log("a:"),
                console.log(a),
                
                t.$http.post(n, a).then((function(e) {
                        var n = e.data.data;
                        n.status ? (t.$message({
                                type: "success",
                                message: n.message || t.i18n.message.OPERATION_COMPLETE
                        }),
                        t.loginData.show = !1,
                        t.setCookieFun(),
                        t.$router.replace({
                                path: "/catalog"
                        }),
                        window.location.reload()) : (t.$alert(n.message || t.i18n.message.OPERATION_ERROR, t.i18n.message.SYSTEM_TXT, {
                                closeOnClickModal: !1,
                                confirmButtonText: t.i18n.message.OK,
                                type: "error"
                        }),
                        t.delCookie("accountInfo")),
                        t.saveLoading = !1
                }
                )).catch((function() {
                        this.saveLoading = !1
                }
                ))
                
        })
)

2 Promise 简介

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理且更强大。

它最早由社区提出并实现,ES6将其写进了语言标准,统一了用法,并原生提供了Promise对象。

特点

  • promise是一个对象

JS中,对象函数的区别就是对象可以保存状态,函数不可以(闭包除外)

  • 摆脱层层链式callback;代码易于理解和维护。并未剥夺函数return的能力,因此无需层层传递callback,进行回调获取数据

  • 多个异步等待合并便于解决

  • 【状态变更的响应处理:then】当promise状态发生改变,就会触发then()里的响应函数处理后续步骤;

  • 【状态变更的不可变更性】但promise状态一经改变,不会再变。

3 Promise 详解

样例/格式

new Promise(
  function (resolve, reject) {
    // 一段耗时的异步操作
    resolve('成功') // 数据处理完成
    // reject('失败') // 数据处理出错
  }
).then(
  (res) => {console.log(res)},  // 成功
  (err) => {console.log(err)} // 失败
)
var funcA = function (a, b) {
        return new Promise(function (resolve, reject) {
                // 一段耗时的异步操作
                console.log(a, b);
                resolve('成功') // 数据处理完成
                // reject('失败') // 数据处理出错  
        });
}

var b = funcA("123", "456").then(
  (res) => {console.log(res)},  // 成功
  (err) => {console.log(err)} // 失败
)
var funcA = function (a, b) {
        //to do some things
        console.log(a+b);
        return new Promise( (resolve, reject) => {
                //to do some things 例如:一段耗时的异步操作
                console.log(a, b);
                resolve('成功') // 数据处理完成
                // reject('失败') // 数据处理出错  
        });
}

var b = funcA("123", "456").then(
  (res) => {console.log(res)},  // 成功
  (err) => {console.log(err)} // 失败
)

2类状态变更的处理: resolve / reject

  • 一旦状态改变就不会再变 (两种状态改变:成功或失败)

    • Pending(进行中) -> Fulfilled(已成功)
    • Pending(进行中) -> Rejected(已失败)
  • resolve

作用: 将Promise对象的状态从“未完成(pending)”变为“成功(resolved)”。

在异步操作成功时调用,并将异步操作的成功结果作为参数传递出去;

  • reject

作用:将Promise对象的状态从“未完成(pending)”变为“失败(rejected)

在异步操作失败时调用,并将异步操作报出的错误信息作为参数传递出去。

Promise对象的3个状态

  • 对象的状态不受外界影响 (3种状态)
    • Pending 状态(进行中)
    • Fulfilled 状态(已成功)
    • Rejected 状态(已失败)

then

Promise实例/对象生成后,可用then方法分别指定两种状态变更处理(resolve/reject)的回调参数。then 方法可以接受两个回调函数作为参数:

  • Promise对象状态改为Resolved时调用 (必选)
  • Promise对象状态改为Rejected时调用 (可选)
function sleep(ms) {
    return new Promise(function(resolve, reject) {
        setTimeout(resolve, ms);
    })
}

sleep(500).then( ()=> console.log("finished"));

这段代码定义了一个函数sleep,调用后,等待了指定参数(500)毫秒后执行then中的函数。值得注意的是,Promise新建后就会立即执行。

执行顺序

接下来我们探究一下它的执行顺序,看以下代码:

let promise = new Promise(function(resolve, reject){
    console.log("AAA");
    resolve()
});
promise.then(() => console.log("BBB"));
console.log("CCC")

// AAA
// CCC
// BBB

执行后,我们发现输出顺序总是 AAA -> CCC -> BBB

表明:在Promise新建后会立即执行,所以首先输出 AAA。然后,then方法指定的回调函数将在当前脚本所有同步任务执行完后才会执行,所以BBB 最后输出。

4 示例

示例1:最简单示例

new Promise(resolve => {
  setTimeout(() => {
    resolve('hello')
  }, 2000)
}).then(res => {
  console.log(res)
})

示例2: 分两次,顺序执行

new Promise(resolve => {
    setTimeout(() => {
      resolve('hello')
    }, 2000)
}).then(val => {
    console.log(val) //  参数val = 'hello'
    return new Promise(resolve => {
      setTimeout(() => {
        resolve('world')
      }, 2000)
    })
}).then(val => {
    console.log(val) // 参数val = 'world'
})

示例3:promise完成后then()

let pro = new Promise(resolve => {
   setTimeout(() => {
     resolve('hello world')
   }, 2000)
});


setTimeout(() => {
   pro.then(value => {
   console.log(value) // hello world
 })
}, 2000);

结论:promise作为队列最为重要的特性,我们在任何一个地方生成了一个promise队列之后,我们可以把他作为一个变量传递到其他地方。

X 参考文献