/** * Evaluate the getter, and re-collect dependencies. */ get () { pushTarget(this) // 设置全局变量 Dep.target,将 Watcher 保存在这个全局变量中 const value = this.getter.call(this.vm, this.vm) // 调用 getter 函数,进入 get 方法进行依赖收集操作 // "touch" every property so they are all tracked as // dependencies for deep watching if (this.deep) { traverse(value) } popTarget() // 将全局变量 Dep.target 置为 null this.cleanupDeps() return value }
notify () { // stablize the subscriber list first const subs = this.subs.slice() for (let i = 0, l = subs.length; i < l; i++) { //遍历 Watcher 列表,调用 update 方法进行更新操作 subs[i].update() } }
functionVue (options) { if (process.env.NODE_ENV !== 'production' && !(thisinstanceofVue)) { warn('Vue is a constructor and should be called with the `new` keyword') } this._init(options) //开始初始化步骤 }
可以看到Dep是连接Observer(生产者)和Watcher(消费者)的关键纽带。Watcher通过getter函数建立起和Observer中Dep的关联。在Observer的setter函数中会触发dep.notify()方法,根据上文对该方法的讲解,它实际上对数组中每个Watcher执行了update方法。在方法中根据是否同步去执行run方法,这个方法中通过源码可以看到实际上正是通过const value = this.get()获取最新的value。
functionasync(request, callback) { // Do something. asyncA(request, function (data) { // Do something asyncB(request, function (data) { // Do something asyncC(request, function (data) { // Do something callback(data); }); }); }); }
functionco(gen) { var ctx = this; var args = slice.call(arguments, 1);
returnnewPromise(function(resolve, reject) { if (typeof gen === 'function') gen = gen.apply(ctx, args); if (!gen || typeof gen.next !== 'function') returnresolve(gen);
onFulfilled();
functiononFulfilled(res) { var ret; try { ret = gen.next(res); } catch (e) { returnreject(e); } next(ret); }
functiononRejected(err) { var ret; try { ret = gen.throw(err); } catch (e) { returnreject(e); } next(ret); }
functionnext(ret) { if (ret.done) returnresolve(ret.value); var value = toPromise.call(ctx, ret.value); if (value && isPromise(value)) return value.then(onFulfilled, onRejected); returnonRejected(newTypeError('You may only yield a function, promise, generator, array, or object, ' + 'but the following object was passed: "' + String(ret.value) + '"')); } }); }
var readFile = function (path) { var ctx = this; returnnewPromise (function (resolve, reject){ readFile.call(ctx, function (err, data){ if (err) reject(err); resolve(data); }); }); }
之后同样使用上节中的生成器函数gen(),并手动执行下一步操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
function* gen() { var d1 = yieldreadFile('file1.js'); console.log(d1); var d2 = yieldreadFile('file2.js'); console.log(d2); }
<divclass="player"> <divclass="player__content"> <videoid="video"src="movie.mov"poster="movie.jpg"width="400"height="200"> Video is not supported. </video> </div> <divclass="player__control"> <inputtype="button"value="Play!"id="video-play"> <spanid="curtime">0</span>/<spanid="duration">0</span> </div> </div>