异步回调
在异步编程中,我们一般都是使用回调函数,我们将一个函数传递给一个异步函数,当任务完成时它将调用这个函数。
function doAsyncTask(cb) {
setTimeout(() => {
console.log("Async Task Calling Callback");
cb();
}, 1000);
}
doAsyncTask(() => console.log("Callback Called"));
以上例子应该非常熟悉了,在开发中经常应用到,doAsyncTask函数在调用异步的时候,就会调用我们的cb 函数,这种就是回调函数,cb其实是个简写,因为叫做callback,所有一般都这样写
Promise API
在es6中,给我们带来了个回调的替代方案promise,其实这个promise在es5的时候就有很多第三方的实现库,最早的时候,在jq就有类似的实现了;
它的功能与回调函数相同,但语法更好,更容易处理错误
创建一个Promise对象
我们通过调用promise类的new来创建一个promise的实例
var promise = new Promise((resolve, reject) => {
});
我们传递给Promise一个内置函数,并且它接受两个内置参数(resolve, reject),我们可以定义了这个函数,里面的两个参数可以随便我们叫什么,但是我们一般通过语义化的叫法,一般都叫做resolve和reject
==resolve和reject其实也是函数体的一部分==
在这个函数中调用异步函数,我们就可以调用resolve(),如下:
var promise = new Promise((resolve, reject) => {
setTimeout(() => {
console.log("Async Work Complete");
resolve();
}, 1000);
});
一般我们返回这个promise实例在一个函数中,如下:
function doAsyncTask() {
var promise = new Promise((resolve, reject) => {
setTimeout(() => {
console.log("Async Work Complete");
resolve();
}, 1000);
});
return promise;
}
如果函数中有报错,将执行reject(),以下代码未完善,error只是表示个意思
function doAsyncTask() {
var promise = new Promise((resolve, reject) => {
setTimeout(() => {
console.log("Async Work Complete");
if (error) {
reject();
} else {
resolve();
}
}, 1000);
});
return promise;
}
我们可以将一个成功的函数附加到then函数中处理,比如:
doAsyncTask().then(() => console.log("Task Complete!"));
then 函数中可以带两个参数,第一个以上代码所示,是成功的回调,而还有一个参数是失败的回调函数,可以写成以下方式:
doAsyncTask().then(
() => console.log("Task Complete!"),
() => console.log("Task Errored!"),
);
传递给resolve和reject函数的任何值都会传递给成功和错误处理程序
let error = true;
function doAsyncTask() {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (error) {
reject('error'); // pass values
} else {
resolve('done'); // pass values
}
}, 1000);
});
}
doAsyncTask().then(
(val) => console.log(val),
(err) => console.error(err)
);
挂载到Promise的resolve和reject
我们可以使用Promise.resolve()方法,直接声明成功回调的方法
let promise = Promise.resolve('done');
同样的也有Promise.reject()方法
let promise = Promise.reject('fail');
接着也可以和正常声明一样,使用then方法执行回调
let promise = Promise.resolve('done');
promise.then((val) => console.log(val)); // 'done'
链式调用
我们可以用then链接做链式调用,因为promise对象每执行完都会返回一个promise对象
Promise.resolve("done")
.then(
(val) => {
console.log(val);
return 'done2';
},
(err) => console.error(err)
)
.then(
(val) => console.log(val),
(err) => console.error(err)
);
// 'done'
// 'done2'
Promise的错误将会在链式中传递,所以我们不需要在每个then中处理错误,只需要在最后一个中调用reject就可以
Promise.reject('fail')
.then((val) => console.log(val))
.then(
(val) => console.log(val),
(err) => console.error(err)
);
如果在成功的回调中有报错,那么promise对象将会捕获错误在reject中
Promise.resolve('done')
.then((val) => {
throw new Error("fail")
})
.then(
(val) => console.log(val),
(err) => console.error(err)
);
// [Error: fail]
catch捕获异常
catch函数是用来捕获异常的函数,这样可以更清晰明确的描述错误
Promise.resolve('done')
.then((val) => {throw new Error("fail")})
.then((val) => console.log(val))
.catch((err) => console.error(err));
总结
Promise能更清晰优雅的写异步回调的代码,捕获异常方面的代码也更加的清晰集中