在实践我迄今为止所学到的有关Babel的ES2015,特别是关于WeakMaps时,我遇到了一个问题,我不知道为什么它不起作用。
我定义了一个WeakMap来容纳来自AJAX调用的数据,只有当所述WeakMap的值为undefined
时才会触发。
这就是我的目标:
class User {
constructor( id ) {
id = Number( id );
if( id <= 0 || isNaN( id ) ) {
throw new TypeError( 'Invalid User ID' );
}
_id.set( this, id );
}
getID() {
return _id.get( this );
}
getData() {
let _this = this;
if( _data.get( _this ) === undefined ) {
_this.loadData().done( function( data ) {
// JSON is indeed successfully loaded
console.log( data );
_data.set( _this, data );
// WeakMap is indeed set correctly
console.log( _data.get( _this ) );
});
}
// But here it's undefined again!
console.log( _data.get( _this ) );
return _data.get( _this );
}
loadData() {
return $.get({
url: '/users/' + _id.get( this, data ),
});
}
}
let _id = new WeakMap;
let _data = new WeakMap;
// ---------------
var user = new User( 1 );
console.log( user.getID(), user.getData() ); // 1 undefined
据我所知,我正在正确设置WeakMap数据,因为正在设置用户ID并且可以检索,但是来自AJAX的用户数据虽然确实是在jQuery.done()内设置的不能在它之外访问。
我做错了什么?
答案 0 :(得分:0)
我不明白JavaScript是不是说这是正确的解决方案但是我已经搜索了很多,在Stack Overflow中阅读了无数的问题,这些答案很难以简单的方式处理,对任何人来说都是如此感兴趣的是:
class User {
constructor( id ) {
id = Number( id );
if( id <= 0 || isNaN( id ) ) {
throw new TypeError( 'Invalid User ID' );
}
_id.set( this, id );
}
getID() {
return _id.get( this );
}
getData() {
if( _data.get( this ) === undefined ) {
_data.set( this, this.loadData() );
}
return _data.get( this );
}
loadData() {
return $.getJSON( CARD_LIST + '/player/' + _id.get( this ) );
}
}
let _data = new WeakMap;
// ---------------
var user = new User( 1 );
user.getData().done( function( data ) {
console.log( data );
})
这不是我最初的想法,我没有解释“为什么”的知识,但至少这是一个明显的工作示例,我谦卑希望这将有助于其他人试图从极端提取信息长答案和/或无益/无指导的评论。
答案 1 :(得分:0)
有关如何使用Ajax等异步操作结果的(冗长)入门,请参阅How do I return the response from an asynchronous call?。
简短的回答是:如果您同步return
某个值,则不能使用异步获取的结果。您的getData
函数在任何Ajax调用解析之前返回,因此同步返回值getData
不能依赖于任何异步获取的值。这甚至不等于等待&#34;足够长:JavaScript事件处理的基本原则是当前函数堆栈(即当前函数和直接调用该函数的函数等)必须在处理任何新事件之前完全解析。处理异步Ajax结果是一个新事件,因此在done
函数执行是古代历史之后,getData
处理程序必然不会运行。
解决问题的两种常用方法是:
使Ajax调用同步
在getData
您可以通过将回调传递到getData
来执行#2,例如
getData(funnction(data) { console.log("If this is running, we finally got the data", data); }
function getData(callback) {
_this.loadData.done(function(data) {
_data.set(this, data);
// etc. etc.
callback(_data.get( _this ));
});
}
所以,现在getData
本身是异步的,这是否会强制你重写你已经拥有的`getData的任何使用,并导致在你的代码中传播异步模式?是的,确实如此。
如果你想使用返回承诺,你可以做
getData().then(function(data) {
console.log("Got the data", data);
});
function getData() {
return _this.loadData().then(function(data) {
_data.set(this, data);
// etc. etc.
return _data.get( _this );
});
}
这是有效的,因为承诺允许链接then
来电。这只是在get数据函数内部和外部链接then
:一个then
回调在getData
内排队,而下一个回调在getData
之外排队。第一个回调的返回值用作第二个回调的参数。 then
的返回值是原始承诺,因此我只使用了return mypromise.then(...)
形式,它返回了相同的对象,就像我刚刚完成return mypromise
一样(但显然我在这种情况下还没有设置回调。)