回调
request('/a', res => {
});
function requestA(cb) {
request('/a', cb);
}
function requestB(params, cb) {
request('/b', params, cb);
}
requestA(params => {
requestB(params, res => {
});
});
let times = 2;
let result = {};
function done(action, data) {
result[action] = data;
if (!--times) {
}
}
request('/a', res => {
done('a', res);
});
request('/b', res => {
done('b', res);
});
订阅/发布
let slice = Array.prototype.slice;
let uid = 0;
let proto = {
_on(name, cb) {
let events = this.events;
let cbs = events[name] || (events[name] = []);
cbs.push(cb);
},
once() {
let args = slice.call(arguments);
let cb = args.pop();
let times = args.length;
let map = {};
let fn = (name, data) => {
map[name] = data;
if (!(--times)) {
cb(map);
this.off(name, fn);
}
};
fn.__uid__ = cb.__uid__ = uid++;
args.forEach(name => {
this._on(name, fn);
});
},
off(name, cb) {
let events = this.events;
let cbs = events[name];
if (cbs) {
for (let i = 0; i < cbs.length; i++) {
if (cb.__uid__ === cbs[i].__uid__) {
cbs.splice(i--, 1);
}
}
}
},
emit(name, data) {
let events = this.events;
let cbs = events[name];
if (cbs) {
cbs = cbs.slice();
cbs.forEach(cb => cb(name, data));
}
}
};
let emiter = Object.create(proto, {
events: {
value: []
}
});
emiter.once('a', ret => {
let params = ret.a;
request('/b', params, res => {
});
});
request('/a', res => {
emiter.emit('a', res);
});
emiter.once('a', 'b', ret => {
let { a, b } = ret;
});
request('/a', res => {
emiter.emit('a', res);
});
request('/b', res => {
emiter.emit('b', res);
});
Deferred/Promise
$.Deferred方法,返回一个deferred对象;该对象拥有一个promise方法,返回一个promise对象。两者的区别在于deferred对象调用resolve或者reject方法。promise存在三种状态:pending , resolved, rejected
then: 接受resolved, rejected, progress三个回调作为参数,返回一个新的promise对象,该promise对象的状态取决于相应回调的返回值,通常用于实现多异步串行或者返回一个新值供后续使用
done: 添加resolved回调
fail: 添加rejected回调
always: 同时添加resolved和rejected的回调
function delay(timeout) {
let deferred = $.Deferred();
setTimeout(_ => deferred.resolve(), timeout);
return deferred.promise();
}
delay(3 * 1000)
.done(_ => {
console.log('这里是3秒后触发');
});
delay(3 * 100)
.then(_ => delay(3 * 1000))
.done(_ => {
console.log('这里6秒后触发');
});
$.get('/a')
.done(res => {
})
.fail(e => {
});
$.get('/a')
.then(resA => $.get('/b'))
.done(resB => {
})
.fail(e => {
});
$.when($.get('/a'), $.get('/b'))
.done((resA, resB) => {
})
.fail(e => {
})
.always(_ => {
});
宏任务(macrotask)与微任务(microtask)
JavaScript的事件队列分为两种:宏任务与微任务。宏任务每次从事件队列取出一个来执行;当当前宏任务执行完毕后,再从微任务的事件队列中取出所有微任务来执行。
macrotask:包括整体代码script, setTimeout, setInterval, setImmediate
microtask:Promise, process.nextTick, Mutation Observer, Message Channel
setTimeout(_ => console.log(1), 0);
Promise.resolve()
.then(_ => console.log(2))
.then(_ => console.log(3));
console.log(4);
ES6 Promise
Promise的then和catch为微任务,执行顺序比setTimeout优先,可以看作浏览器端的process.nextTick。同时Vue.nextTick也是优先基于Promise来实现。promise存在三种状态:pending , resolved, rejected
then: 接受resolved, rejected两个回调函数作为参数,返回一个新的promise对象,该对象的状态取决于相对应回调的返回值
catch: 接受rejected回调函数作为参数,返回一个新的promise对象,该对象的状态取决于回调的返回值
Promise.resolve()
.then(_ => Promise.reject())
.then(_ => console.log('then'))
.catch(_ => console.log('reject'))
axios.get('/a')
.then(res => {
})
.catch(e => {
});
axios.get('/a')
.then(resA => axios.get('/b'))
.then(resB => {
})
.catch(e => {
});
Promise.all([
axios.get('/a'),
axios.get('/b')
])
.then(([resA, resB]) => {
})
.catch(e => {
})
.then(_ => {
});
Generator
Promise配合Generator,真正的同步写法实现异步功能来临!!!
function so(fn) {
return function() {
let args = Array.prototype.slice.call(arguments, 0);
return new Promise((resolve, reject) => {
let generator = fn.apply(null, args);
function onFullfilled(ret) {
if (ret.done) {
return resolve(ret.value);
}
let promise = ret.value;
if (!(promise instanceof Promise)) {
promise = Promise.resolve(promise);
}
promise
.then(res => {
try {
onFullfilled(generator.next(res));
} catch(e) {
reject(e);
}
})
.catch(e => {
try {
generator.throw(e);
} catch(e) {
reject(e);
}
});
}
try {
onFullfilled(generator.next());
} catch(e) {
reject(e);
}
});
}
}
let i = 0;
function delay(timeout) {
return new Promise((resolve, reject) => {
setTimeout(resolve, timeout, i++);
});
}
function *go() {
let v1 = yield delay(3 * 1000);
console.log(`3s后输出: ${v1}`);
let v2 = yield delay(3 * 1000);
console.log(`6s后输出: ${v2}`);
return yield delay(3 * 1000);
}
so(go)().then(v => console.log(`9s后输出: ${v}`)).catch(e => console.log(e.message));
function *request() {
let r1 = yield axios.get('/a');
let r2 = yield aixos.get('/b', { params: { id: r1.id } });
}
so(request)().catch(e => {});
function *request() {
let [r1, r2] = yield Promise.all([axios.get('/a'), axios.get('/b')];
}
so(request)().catch(e => {});
async/await
Promise配合Generator的超级语法糖,有点甜
async function request() {
let r1 = await axios.get('/a');
let r2 = await aixos.get('/b', { params: { id: r1.id } });
}
request().catch(e => {});
async function request() {
let [r1, r2] = await Promise.all([axios.get('/a'), axios.get('/b')];
}
request().catch(e => {});