背景
异步,同步和回调,简单来说
- 同步:能直接拿到结果
- 异步:不能直接拿到结果
- 回调:写给别人用的函数(将来调用)
如何判断是否是异步函数
如果一个函数的返回值处于 - setTimeout
- AJAX
- addEventListener
中,那么就是异步的。
可是到了后来,异步就会有好几个返回值,怎么搞?
promise
当我们有多个回调函数时,就会有像这样
doSomething(function(result) {
doSomethingElse(result, function(newResult) {
doThirdThing(newResult, function(finalResult) {
console.log('Got the final result: ' + finalResult);
}, failureCallback);
}, failureCallback);
}, failureCallback);
一直调用下去,这还是少的,才三个,这么对怎么办?
同时这种写法还有另外两个问题:
- 回调函数命名缺乏规范, 每个程序员都有可能给回调函数起不同的名字
- 不能很好地捕获错误
怎样才能解决上面的问题
答:用promise
promise优点
- 解决回调地狱,增强代码可读性
- 规范回调的名字或顺序
- 很方便地捕获错误
下面我们来看看怎么使用
doSomething().then(function(result) {
return doSomethingElse(result);
})
.then(function(newResult) {
return doThirdThing(newResult);
})
.then(function(finalResult) {
console.log('Got the final result: ' + finalResult);
})
.catch(failureCallback);
以上的回调函数还可以简化为箭头函数
doSomething()
.then(result => doSomethingElse(result))
.then(newResult => doThirdThing(newResult))
.then(finalResult => {
console.log(`Got the final result: ${finalResult}`);
})
.catch(failureCallback);
是不是感觉好了一点,当回调函数越来越多时,就会像这样看起来很清晰。
创建一个promise
Promise 对象是由关键字 new 及其构造函数来创建的。该构造函数接受两个函数——resolve 和 reject ——作为其参数。当异步任务顺利完成且返回结果值时,会调用 resolve 函数;而当异步任务失败且返回失败原因(通常是一个错误对象)时,会调用reject 函数。resolve函数和reject函数都只接受一个参数
const myFirstPromise = new Promise((resolve, reject) => {
// ?做一些异步操作,最终会调用下面两者之一:
//
// resolve(someValue); // fulfilled
// ?或
// reject("failure reason"); // rejected
});
想让一个函数有Promise对象的功能:
return new Promose( (resolve, reject) => { )
function myAsyncFunction(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.onload = () => resolve(xhr.responseText); // 成功就调用resolve函数
xhr.onerror = () => reject(xhr.statusText); // 失败就调用reject函数
xhr.send();
});
};
易混淆点:resolve 和 reject 和 then(succes, fail)
new Promise(function(resolve, reject){}里的resolve 和 reject 并不是 .then(succes, fail) 里面的 success 和 fail,resolve 会去调用 success,reject 会去调用 fail
Promise使用方法小结
第一步
- return new Promise((resolve, reject) =>{…})
- 任务成功就调用 resolve.call(null, result)
- 任务失败就调用 reject.call(null, errorMessage)
- resolve和reject会再去调用成功和失败函数
第二步
- 使用.then(success, fail) 传入成功和失败函数
- success.call(null, result) 参数来自resolve
- fail.call(null, errorMessage) 参数来自reject