.then()在promise解决之前触发

Emi*_*mil 3 javascript promise

在我的vanilla js项目中,我有一系列承诺:

API.POST({link to login endpoint}, "email=foo&pass=bar")
.then(() => User.initiate(API))
.then(() => console.log(User.name || 'wat'));
Run Code Online (Sandbox Code Playgroud)

除了请求类型之外,API对象的POST和GET方法看起来都相同:

GET (url, params = null) {
    console.log("GET start");
    return new Promise((resolve,reject) => {
        this._request('GET', url, params)
        .then(result => resolve(result));
    });
}

POST (url, params = null) {
    return new Promise((resolve,reject) => {
        this._request('POST', url, params)
        .then(result => resolve(result));
    });
}
Run Code Online (Sandbox Code Playgroud)

...以及负责发送请求的_request方法:

_request (type, url, params = null) {
    return new Promise((resolve, reject) => {
        var xhr = new XMLHttpRequest();
        xhr.responseType = 'json';
        xhr.open(type,url,true);
        xhr.withCredentials = true;
        xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=UTF-8");
        xhr.onload = function(){
            if (this.status == 200) {
                console.log(type + ' done');
                resolve(this.response);
            } else {
                reject(this.response._status.code);
            }
        };

        xhr.send(params);

    });
}
Run Code Online (Sandbox Code Playgroud)

App的User对象提供"启动"方法,该方法调用API以检查用户是否已登录.使用肯定响应API返回_embedded.user对象,在下一步中用于填充应用程序的用户属性:

initiate(API) {
    API.GET({link to authorization check endpoint})
    .then(authData => this.regenerate(authData._embedded.user));
},
regenerate(userData) {
    this.name = userData.name;

    // and so on, for each User property

    return new Promise((resolve,reject) => {
        resolve(this);
    });
}
Run Code Online (Sandbox Code Playgroud)

我期望发生的是:

  1. 发送API登录请求(这只是为了跳过与当前工作无关的实际登录过程)
  2. API返回cookie,允许作为已登录用户进行进一步测试
  3. 发送API请求以询问用户是否经过身份验证
  4. API使用confirm和_embedded.user对象进行响应
  5. 应用程序的用户对象的属性由API响应中的数据填充
  6. User.name在控制台中记录

步骤6虽然在步骤3和4之间触发,但我找不到原因.我的控制台看起来如下(注意上面的API对象代码中的console.logs):

POST完成了

开始吧

WUT

完成

这可能是什么原因?提前致谢.

cha*_*tfl 6

缺少returninitiate()

initiate(API) {
   return API.GET({link to authorization check endpoint})
   //^^ return the promise
    .then(authData => this.regenerate(authData._embedded.user));
}
Run Code Online (Sandbox Code Playgroud)

在GET和POST方法中也使用promise反模式.因为_request()已经返回了一个promise,所以不需要在每个中创建一个新的promise

所有你需要的是:

GET (url, params = null) {
    return this._request('GET', url, params);
}

POST (url, params = null) {
    return this._request('POST', url, params);       
}
Run Code Online (Sandbox Code Playgroud)

有关更详细的说明,请参阅什么是显式承诺构造反模式以及如何避免它?


而不是使用XMLHttpRequest你可能也想看看使用更新的fetch() API内置承诺和更好的错误处理