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

时间:2018-05-30 20:20:26

标签: javascript promise

在我的vanilla js项目中,我有以下承诺链:

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

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));
    });
}

...以及负责发送请求的_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);

    });
}

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);
    });
}

我期望发生的事情是:

  1. 发送API登录请求(这只是为了跳过与当前工作无关的实际登录过程)
  2. API返回cookie,允许以记录用户身份进行进一步测试
  3. 发送API请求以询问用户是否经过身份验证
  4. API使用确认和_embedded.user对象
  5. 进行响应
  6. App的User对象的属性由API响应中的数据填充
  7. 在控制台中记录User.name
  8. 步骤6虽然在步骤3和4之间触发,但我找不到原因。我的控制台看起来如下(请注意上面API对象代码中的console.logs):

      

    POST完成

         

    GET开始

         

    但是

         

    GET完成

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

1 个答案:

答案 0 :(得分:6)

return

中缺少initiate()
initiate(API) {
   return API.GET({link to authorization check endpoint})
   //^^ return the promise
    .then(authData => this.regenerate(authData._embedded.user));
}

在GET和POST方法中也使用promise反模式。由于_request()已经返回承诺

,因此无需在每个承诺中创建新承诺

您只需要:

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

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

有关详细说明,请参阅What is the explicit promise construction antipattern and how do I avoid it?

您可能还希望查看使用内置承诺和更好的错误处理的最新fetch() API,而不是使用XMLHttpRequest