1、回调
什么是回调?
个人理解,让函数有序的执行。
示例:
function loadScript(src,callback){
let script = document.createElement('script');
script.src = src;
script.onload =()=>calllback(script);
document.head.append(script);
}
loadScript('src',script=>{
alert('ok');
});
也可以在回调函数中继续回调,但是这样会导致回调金字塔,或者地狱。
2、Promise
Promise 对象的构造语法
let promise = new Promise(function(resolve,reject){
//executror
});
promise 对象有内部属性
state -----最初是 pending,然后被改为‘fulfilled“ 或”rejected“
result -----一个任意值,最初是undefined
当executor 完成任务时,应用调用下列之一
消费者:”.then“ 和”.catch"
promise 对象充当生产者,和消费函数之间的连接。
.then 的语法;
promise.then(
function(result){}
function(error){}
);
示例:
let promise = new Promise(function(resolve,reject){
setTimeout(()=>resolve("done"),1000);
});
promise.then(
result=>alert(result),
error=>alert(error)
);
其中成功和失败也可以只选其一,操作如下
只对成功的进行操作;
let promise = new Promise(resolve=>resolve("done!"));
promise.then(alert);
对错误有两种操作
let promise = new Promise((resolve,reject)=>{
setTimeout(()=>reject(new Error("cuole!")),1000);
});
promise.then(null,alert);
简写:promise.catch(alert);
实践
function loadScript(src){
return new Promise(function(resolve,reject){
let script document.createElement('script');
script.src = src;
script.onload=()=>resolve(script);
script.onerror=()=>reject(new Error("Script load error: " + src));
document.head.append(script);
});
}
let promise = loadScript('src');
promise.then(
script=>alert(`${script.src} is loaded!`),
error=>alert(`Error:${error.message}`)
);
promise.then(script=>alert('one more handler to do something');
3、Promises 链
示例:
1 new Promise(function(resolve, reject) { 2 3 setTimeout(() => resolve(1), 1000); // (*) 4 5 }).then(function(result) { // (**) 6 7 alert(result); // 1 8 return result * 2; 9 10 }).then(function(result) { // (***) 11 12 alert(result); // 2 13 return result * 2; 14 15 }).then(function(result) { 16 17 alert(result); // 4 18 return result * 2; 19 20 });
.then 返回的是promises
1 new Promise(function(resolve, reject) { 2 3 setTimeout(() => resolve(1), 1000); 4 5 }).then(function(result) { 6 7 alert(result); // 1 8 9 return new Promise((resolve, reject) => { // (*) 10 setTimeout(() => resolve(result * 2), 1000); 11 }); 12 13 }).then(function(result) { // (**) 14 15 alert(result); // 2 16 17 return new Promise((resolve, reject) => { 18 setTimeout(() => resolve(result * 2), 1000); 19 }); 20 21 }).then(function(result) { 22 23 alert(result); // 4 24 25 });
这里第一个 .then
显示 1
并在 (*)
行返回 new Promise(…)
,一秒之后它会 resolve 掉,然后 result(resolve
的参数,在这里它是 result*2
)被传递给位于 (**)
行的第二个 .then
。它会显示 2
,而且执行相同的动作。
所以输出还是 1 → 2 → 4,但是现在每次 alert
调用之间会有 1 秒钟的延迟。
示例 loadScript
1 loadScript("/article/promise-chaining/one.js") 2 .then(script => loadScript("/article/promise-chaining/two.js")) 3 .then(script => loadScript("/article/promise-chaining/three.js")) 4 .then(script => { 5 // 脚本被加载,我们可以使用声明过的函数了 6 one(); 7 two(); 8 three(); 9 });
示例 fetch
基本语法: let promise = fetch(url);
function loadJson(url) { return fetch(url) .then(response => response.json()); } function loadGithubUser(name) { return fetch(`https://api.github.com/users/${name}`) .then(response => response.json()); } function showAvatar(githubUser) { return new Promise(function(resolve, reject) { let img = document.createElement('img'); img.src = githubUser.avatar_url; img.className = "promise-avatar-example"; document.body.append(img); setTimeout(() => { img.remove(); resolve(githubUser); }, 3000); }); } // 使用它们 loadJson('/article/promise-chaining/user.json') .then(user => loadGithubUser(user.name)) .then(showAvatar) .then(githubUser => alert(`Finished showing ${githubUser.name}`)); // ...
4、Promise API
在Promise 类中,有5种静态方法。如下
Promise.resolve
语法:let promise = Promise.resolve(value);
1 function loadCached(url) { 2 let cache = loadCached.cache || (loadCached.cache = new Map()); 3 4 if (cache.has(url)) { 5 return Promise.resolve(cache.get(url)); // (*) 6 } 7 8 return fetch(url) 9 .then(response => response.text()) 10 .then(text => { 11 cache.set(url,text); 12 return text; 13 }); 14 }
Promise.reject
语法: let promise = Promise.reject(error);
let
promise =
new
Promise
(
(
resolve
,
reject)
=>
reject
(
error)
)
;
Promise.all
let promise = Promise.all([...promises...]);
1 Promise.all([ 2 new Promise(resolve => setTimeout(() => resolve(1), 3000)), // 1 3 new Promise(resolve => setTimeout(() => resolve(2), 2000)), // 2 4 new Promise(resolve => setTimeout(() => resolve(3), 1000)) // 3 5 ]).then(alert); // 1,2,3 当 promise 就绪:每一个 promise 即成为数组中的一员
Promise.allSettled
1 let urls = [ 2 'https://api.github.com/users/iliakan', 3 'https://api.github.com/users/remy', 4 'https://no-such-url' 5 ]; 6 7 Promise.allSettled(urls.map(url => fetch(url))) 8 .then(results => { // (*) 9 results.forEach((result, num) => { 10 if (result.status == "fulfilled") { 11 alert(`${urls[num]}: ${result.value.status}`); 12 } 13 if (result.status == "rejected") { 14 alert(`${urls[num]}: ${result.reason}`); 15 } 16 }); 17 });
Promise.race
语法:let promise = Promise.race(iterable);
1 Promise.race([ 2 new Promise((resolve, reject) => setTimeout(() => resolve(1), 1000)), 3 new Promise((resolve, reject) => setTimeout(() => reject(new Error("Whoops!")), 2000)), 4 new Promise((resolve, reject) => setTimeout(() => resolve(3), 3000)) 5 ]).then(alert); // 1
第一个结果/错误会成为整个 Promise.race
的结果。在第一个 promise 被解决(“赢得比赛[wins the race]”)后,所有后面的结果/错误都会被忽略。
5、Async/await
Async functions
async fucntion f(){
return 1;
}
f().then(alert);//1
async 确保函数返回值是一个promise。
Await
语法:let value = await promise;
要求:await 不能在普通方法中使用,必须在 async 函数中才有效。
1 async function showAvatar() { 2 3 // 读取 JSON 4 let response = await fetch('/article/promise-chaining/user.json'); 5 let user = await response.json(); 6 7 // 读取 github 用户信息 8 let githubResponse = await fetch(`https://api.github.com/users/${user.name}`); 9 let githubUser = await githubResponse.json(); 10 11 // 显示头像 12 let img = document.createElement('img'); 13 img.src = githubUser.avatar_url; 14 img.className = "promise-avatar-example"; 15 document.body.append(img); 16 17 // 等待 3 秒 18 await new Promise((resolve, reject) => setTimeout(resolve, 3000)); 19 20 img.remove(); 21 22 return githubUser; 23 } 24 25 showAvatar();
在类方法中的使用
class Waiter{
async wait(){
retrun await Promise.resolve(1);
}
}
new Waiter()
.wait()
.then(alert);//1