Promise响应参数丢失

3
我正在学习由浏览器提供的 Promise,并且在处理响应参数时遇到了困难,导致它无法返回。这是我的代码:

/* uploads a resource to the given server and runs the callback function when done */
function upload(serverUrl, resource, successfulCallback, failCallback) {
    console.log("upload successfulCallback: ", successfulCallback);
    console.log("upload failCallback: ", failCallback);
 var jqxhr = $.ajax({
  url: serverUrl,
  method: "POST",
  type: "POST",
  contentType: "application/json",
  data: encode(resource),
  headers: {
            Accept: "application/json; charset=utf-8",
            Prefer: "return=minimal"
        }
 }).done(function() {
        console.log("Upload done, jqxhr: ", jqxhr);
  successfulCallback(jqxhr);
 }).fail(function(err) {
  console.log("upload failed: " + err.responseText);
  failCallback(jqxhr, err);
 });
}

function validate(endpoint, resource) {
    var parameters = {
        "resourceType": "Parameters",
        "parameter": [{
            "name": "resource",
            "resource": resource            
        }]        
    };
     
    return new Promise(function (resolve, reject) {
        console.log("Made new promise, resolve function is: ", resolve);
        console.log("Made new promise, reject function is: ", reject);
        upload(endpoint + '/' + resource.resourceType + "/$validate", parameters, resolve, reject);
    });
}

这是我如何使用它:

    validate("http://fhir3.healthintersections.com.au/open", decode(leftFhirView.getValue()))
        .then(function(response) {
            console.log("It worked! '", response, "'");
        }, function(error) {
            console.error("Failed validation!", error.stack);
        });

以下是我运行时得到的调试输出:
main.js:45 Made new promise, resolve function is:  u() { [native code] }
main.js:46 Made new promise, reject function is:  v() { [native code] }
main.js:14 upload successfulCallback:  u() { [native code] }
main.js:15 upload failCallback:  v() { [native code] }
main.js:27 Upload done, jqxhr:  Object {readyState: 4, responseText: "", <snip>
main.js:196 It worked! '  '

你可以看到,在 successfulCallback(jqxhr) 和 response 函数之间,我的 jqxhr 变成了两个空格。发生了什么事情?


1
实际上,它并没有变成两个空格,而是变成了一个空字符串 - 这两个空格是由console.log放置的 - 尝试使用typeof response来查看你正在解析的内容 - responseText是一个空字符串,但你的代码仍然应该解析为在第27行记录的jqxhr对象。 - Jaromanda X
你应该在upload函数内部创建一个new Promise,并从那里return它,这样你就不必处理回调参数了。 - Bergi
2个回答

0

通过将jQuery Promise一路返回到验证函数中来修复它。


0

为了解释@Jaromanda X在评论中所说的内容。

您正在尝试在另一个Promise内部解决一个Promise。原始的Promise对象不会传递给then的回调函数。相反,它将是原始Promise对象中的响应文本。

在这种情况下,jqxhr是原始的Promise$.ajax返回一个Promise对象),其响应文本为""。这就是为什么您得到一个空字符串的原因。

根据MDN的文档,您的代码与下面的示例相同

var original = Promise.resolve(true);
var cast = Promise.resolve(original);
cast.then(function(v) {
  console.log(v); // true
});

更新于11/14/16

由@Bergi指出,jqxhr不是Promise的实例,而是一个带有属性then(类似promise)的JQuery延迟对象。但是,Promise.then会寻找jqxhr.then,如果存在这样的属性,则异步解决promise。


抱歉,我还是有点困惑。我的上传没有失败,那么为什么响应文本会起作用呢?我也没有在upload()函数内返回jqxhr承诺,而是使用回调(这样承诺就不会太复杂了)。 - Vadim Peretokin
实际上,我并没有表达那个意思 - 我实际上看不出为什么OP在then中获取的是responseText而不是已解决的对象jqxhr。 - Jaromanda X
@Vadi 是的,您没有返回 jqxhr,但是 jqxhr.reponseText 成为 then 中回调函数的参数。在 jqxhr 解析后,将调用 successfulCallback(jqxhr)。由于 jqxhr instanceof Promise === true,因此 .then(function(response) {...})response 参数的引用实际上是 jqxhr.reponseText。请查看此链接 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/resolve。 - Z.Z.
@Z.Z. jqXhr instanceof Promise 是 false,但它是一个带有 then 方法的 jQuery 延迟对象,因此它将被类似于 Promise 的方式吸收。 - Bergi
@Bergi,那很有道理。谢谢! - Z.Z.
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接