Promise 链在内部 Promise 被解决之前继续 [英] Promise chain continues before inner promise is resolved

查看:17
本文介绍了Promise 链在内部 Promise 被解决之前继续的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在内部承诺解决之前承诺解决的类似问题,但我可以'尽管如此,还是要让它工作.

Similar question to Promise resolve before inner promise resolved but I can't get it to work nontheless.

每次我认为我理解了 Promise 时,我就证明自己错了!

Every time I think I understand promises, I prove myself wrong!

我有这样写的函数

function getFileBinaryData () {
    var promise = new RSVP.Promise(function(resolve, reject){
        var executorBody = {
            url: rootSite + sourceRelativeUrl + "/_api/web/GetFileByServerRelativeUrl('" + fileUrl + "')/$value",
            method: "GET",
            binaryStringResponseBody: true,
            success: function (fileData) {
                resolve(fileData.body);
            },
            error: function  (argument) {

                alert("could not get file binary body")
            }            
        }
        sourceExecutor.executeAsync(executorBody);
    });
    return promise;
}

function copyFileAction (fileBinaryData) {
    var promise = new RSVP.Promise(function(resolve, reject){
        var executorBody = {
            url: rootSite + targetWebRelativeUrl + "/_api/web/GetFolderByServerRelativeUrl('" + targetList + "')/Files/Add(url='" + fileName + "." + fileExt + "', overwrite=true)",
            method: "POST",
            headers: {
                "Accept": "application/json; odata=verbose"
            },
            contentType: "application/json;odata=verbose",
            binaryStringRequestBody: true,
            body: fileBinaryData,
            success: function (copyFileData) {
                resolve();
            },
            error: function  (sender, args) {

            }
        }
        targetExecutor.executeAsync(executorBody);    
    });
    return promise;
}

我试着像这样链接

$.getScript("/_layouts/15/SP.RequestExecutor.js")
            .then(patchRequestExecutor)
            .then(function(){
                sourceExecutor = new SP.RequestExecutor(sourceFullUrl);
                targetExecutor = new SP.RequestExecutor(targetList);
            })
            .then(getFileInformation)
            .then(getFileBinaryData)
            .then(copyFileAction)
            .then(getTargetListItem)
            .then(updateTargetListItem)
            .catch(function (sender, args) {

            });

或者像这样

$.getScript("/_layouts/15/SP.RequestExecutor.js")
            .then(patchRequestExecutor)
            .then(function(){
                sourceExecutor = new SP.RequestExecutor(sourceFullUrl);
                targetExecutor = new SP.RequestExecutor(targetList);
            })
            .then(function(){
                return getFileInformation();
            })
            .then(function(){
                return getFileBinaryData();
            })
            .then(function(binaryData){
                return copyFileAction(binaryData)
            })
            .then(function(){
                return getTargetListItem();
            })
            .then(function(listItem){
                return updateTargetListItem(listItem);
            });

问题是,即使我返回新的承诺,在任何内部承诺得到解决之前,执行仍在链中继续下去.怎么来的?难道不应该等到异步请求成功并在success回调中调用resolve()?

The problem though is that even if I return new promises, the execution continues down the chain before any of the inner promises are resolved. How come? Shouldn't it wait until the asynchronous request has succeeded and resolve() is called in the success callback?

推荐答案

您在这里没有做错任何事.这是 jQuery 的错,经常1.

You've done nothing wrong here. This is jQuery's fault, as so often1.

问题在于 jQuery 与 Promises/A+ 不兼容(直到 v 3.0),并且无法采用承诺/thenable 来自其他实现而不是它自己的实现.因此,当您的回调确实返回 RSVP 承诺时,jQuery 只是将它们视为要实现的值,而不是等待它们.
可以将你所有的承诺都投射到一个 jQuery deferred 并且它会起作用,但你真的不想要那样.要使标准的 Promise 行为(由 RSVP 提供)起作用,您需要避免 jQuery 的错误 then.这可以轻松完成:

The problem is that jQuery is not Promises/A+ compatible (until v 3.0), and fails to adopt promises/thenable from other implementations than its own. So when your callbacks do return RSVP promises, jQuery just treats them as values to fulfill with, instead of waiting for them.
You could cast all of your promises to a jQuery deferred and it would work, but you really don't want that. To get the standard Promise behaviour (as offered by RSVP) to work, you will need to avoid jQuery's buggy then. This can easily be done:

RSVP.Promise.resolve($.getScript("/_layouts/15/SP.RequestExecutor.js"))
//   ^^^^^^^^^^^^^^^
    .then(patchRequestExecutor)
    .then(function(){
        sourceExecutor = new SP.RequestExecutor(sourceFullUrl);
        targetExecutor = new SP.RequestExecutor(targetList);
    })
    .then(getFileInformation)
    .then(getFileBinaryData)
    .then(copyFileAction)
    …

这篇关于Promise 链在内部 Promise 被解决之前继续的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆