【问题标题】:.then() fires before promise resolves.then() 在 promise 解决之前触发
【发布时间】:2018-05-31 04:39:51
【问题描述】:

在我的 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 以检查用户是否登录的“initiate”方法。通过肯定响应 API 返回一个 _embedded.user 对象,在下一步中用于填充应用的 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. 应用的 User 对象的属性由 API 响应中的数据填充
  6. User.name 已登录控制台

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

发布完成

开始

呜呜

完成

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

【问题讨论】:

标签: javascript promise


【解决方案1】:

initiate() 中缺少 return

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

还在 GET 和 POST 方法中使用 promise 反模式。由于_request() 已经返回了一个promise,因此无需在每个promise 中创建一个新的promise

你只需要:

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?


除了使用XMLHttpRequest,您可能还想看看使用更新的fetch() API,它内置了承诺和更好的错误处理

【讨论】:

    猜你喜欢
    • 2020-12-27
    • 1970-01-01
    • 2019-02-27
    • 2017-09-24
    • 1970-01-01
    • 2021-09-14
    • 1970-01-01
    • 2017-10-08
    • 1970-01-01
    相关资源
    最近更新 更多