课程名称: 破解JavaScript高级玩法
课程章节: 爱上异步编程
主讲老师: Cloud
课程内容:
今天学习的内容包括:
现代异步编程的核心:Promise
课程收获:
10.1 心得:
回调函数:
function login(callback) {
setTimeout(() => {
callback("token");
}, 3000);
}
function getOrderId(token,callback) {
if(token){
setTimeout(() => {
callback("orderId");
}, 2000);
}
}
function orderDetails(orderId,callback) {
if(orderId){
setTimeout(() => {
callback("淘宝订单:购买xxx书一本");
}, 1500);
}
}
login((token) => {
getOrderId(token,(orderId) => {
orderDetails(orderId,(orderInfo) => {
console.log(orderInfo);
});
});
});
回调函数异常:
function login(callback) {
setTimeout(() => {
callback("token");
}, 2);
}
function getOrderId(token,callback) {
if(token){
setTimeout(() => {
callback("orderId");
}, 3);
}
}
function orderDetails(orderId,callback) {
if(orderId){
setTimeout(() => {
callback("淘宝订单:购买xxx书一本");
}, 2);
}
}
try{
login((token) => {
throw new Error("orderList");
getOrderId(token,(orderId) => {
orderDetails(orderId,(orderInfo) => {
console.log(orderInfo);
});
});
});
}catch(e){
console.log("try catch error:",e);
}
简版延迟函数:
/**
*
*
* @param {any} fn 需要延迟的方法
* @param {any} delay 延迟时间
* @param {any} context 上下文
* @returns
*/
function delay(fn, delay, context) {
let defaultDelay = delay || 5000;
let ticket;
return {
run(...args) {
ticket = setTimeout(async () => {
fn.apply(context, args);
}, defaultDelay)
},
cancel: () => {
clearTimeout(ticket);
}
}
}
const { run, cancel } = delay(() => { console.log("111") }, 3000);
run();
setTimeout(() => {
cancel();
}, 1000);
延迟函数:
function isFunction(fn) {
return typeof fn === 'function' || fn instanceof Function
}
/**
*
*
* @param {any} fn 需要延迟的方法
* @param {any} delay 延迟时间
* @param {any} context 上下文
* @returns
*/
function delay(fn, delay, context) {
let defaultDelay = delay || 5000;
if (!isFunction(fn)) {
return {
run: () => Promise.resolve(),
cancel: noop
}
}
let ticket;
let executed = false;
return {
run(...args) {
return new Promise((resolve, reject) => {
if (executed === true) {
return;
}
executed = true;
ticket = setTimeout(async () => {
try {
const res = await fn.apply(context, args);
resolve(res);
} catch (err) {
reject(err)
} finally {
clearTimeout(ticket);
}
}, defaultDelay)
})
},
cancel: () => {
clearTimeout(ticket);
}
}
}
//测试
const { run, cancel } = delay(() => { return "函数执行结果" }, 3000);
run().then((result) => {
console.log("result:", result);
})
run().then(() => {
console.log("多次调用run result:", result);
});
重试多次:
function isFunction(fn) {
return typeof fn === 'function' || fn instanceof Function
}
function retry(fun, count, assert = () => false) {
if (!isFunction(fun)) {
return Promise.resolve();
}
return new Promise(async (resolve, reject) => {
let error = null; //错误值
for (let tryCount = 1; tryCount <= count; tryCount++) {
try {
const value = await fun(tryCount);
if (assert(value, tryCount)) {
return resolve(value);
}
} catch (e) {
error = e;
}
}
reject(new Error("多次尝试失败"))
});
}
// retry(()=>{
// throw new Error("错误")
// },3).catch((e)=>{
// console.log("捕获到错误:",e)
// });
let index = 0;
function createPromise(tryCount) {
console.log("尝试次数:", tryCount)
return new Promise((resolve, reject) => {
index++;
setTimeout(() => { resolve(index) }, 1000)
})
}
retry(createPromise, 10, (res) => {
return res == 5
}).then((res) => {
console.log("当前的数据:", res);
}).catch((e) => {
console.log("捕获到错误:", e)
});
EventEmitter:
import { BaseAsyncMessager, BaseReqData, GlobalReqOptions } from "../src/index";
import EventEmitter from "events";
const emitter = new EventEmitter();
interface RequestData extends BaseReqData {
method: string;
data?: any;
}
type ResponseData = RequestData;
// 初始化异步Messager
const emitterAsyncMessager = new BaseAsyncMessager<RequestData>({
subscribe(onMessage) {
console.log("emitterAsyncMessager: subscribe");
emitter.on("message", onMessage as any);
return () => {
emitter.off("message", onMessage as any);
}
},
getReqCategory(data: RequestData) {
console.log("emitterAsyncMessager: getReqCategory: method", data.method);
return data.method;
},
getResCategory(data: ResponseData) {
return data.method;
},
request(data: RequestData, key?: string) {
emitter.emit("message-request", data);
}
});
/* 模拟emitter另外一端 */
// 传统的事件通知
setInterval(() => {
emitter.emit('message', {
method: 'continuous-event',
data: new Date().toLocaleTimeString()
})
}, 3000)
// 监听 message-request 事件,然后回发事件
emitter.on("message-request", (data: RequestData) => {
setTimeout(() => {
emitter.emit("message", {
method: data.method,
data: `${data.method}--- data`
})
}, 3000)
})
/*使用方 */
// 调用
emitterAsyncMessager.invoke({
method: "cccc",
data: 111
}).then(res => console.log("res:", res))
// 传统的监听事件
emitterAsyncMessager.addHandler("continuous-event", function onEvent(data) {
console.log("continuous-event:", data);
})
iframe:
<iframe src="./iframe1.html" id="ifr"></iframe>
<script src="../../dist/asyncMessager.js"></script>
<script>
function sendMessage(msg) {
iframe1.contentWindow.postMessage(msg)
}
const iframe1 = document.getElementById("ifr");
const asyncMessager = new AsyncMessager.BaseAsyncMessager({
// logUnhandledEvent: false,
subscribe(onMessage) {
function onIframeMessage(msg) {
onMessage(msg.data);
}
window.addEventListener("message", onIframeMessage);
return () => {
window.removeEventListener("message", onIframeMessage);
}
},
getReqCategory(data) {
console.log("asyncMessager getReqCategory: method", data.method);
return data.method;
},
getResCategory(data) {
return data.method;
},
request(data, key) {
sendMessage(data);
}
});
iframe1.contentWindow.onload = () => {
asyncMessager.invoke({
method: "init",
data: {
user: 123456,
token: "blabla......"
}
}).then(res => console.log("index.html:", res, res))
}
asyncMessager.addHandler("timeInfo", function(data){
console.log("index.html:timeInfo", data);
})
</script>
socket.io:
const socket = io("http://localhost:3000");
function sendMessage(msg) {
socket.emit("message", msg)
}
const asyncMessager = new AsyncMessager.BaseAsyncMessager({
// logUnhandledEvent: false,
subscribe(onMessage) {
function onSocketMessage(msg) {
onMessage(msg);
}
socket.on("message", onSocketMessage);
return () => {
socket.off("message", onSocketMessage);
}
},
request(data, key) {
sendMessage(data);
}
});
socket.on("connect", () => {
console.log("connect")
asyncMessager.invoke({
method: "getUsers",
data: {
user: 123456,
token: "blabla......"
}
}).then(res => console.log("index.html:", res, res))
});
asyncMessager.addHandler("timeInfo", function (data) {
console.log("index.html:timeInfo", data);
});