Promise.then绑定问题

Promise.then bind issue

我在将值绑定到 next Promise 时遇到了问题。看看下面的代码,它会更好地说明情况。

'use strict';

function FindEvent(eventId) {
    console.log('Event:', eventId);
    return Promise.resolve({title: 'MyEvent'});
}

function FindUser(userId) {
    console.log('User:', userId);
    return Promise.resolve({username: 'MyUser'});
}

function MyServiceProblem(payload) {
    payload.userId = 'blah';
    return FindEvent(payload.eventId)
        .then((event) => {
            payload.userId = 'test';
            // setting a breakpoint here shows
            // that the value to payload.userId has been
            // assigned, i.e. 'test'

            return Promise.resolve(payload);
        })
        .then(FindUser.bind(this, payload.userId));
        // But new value doesn't reaches inside FindUser
}

MyServiceProblem({ // userId is 'blah', why not 'test'
    eventId: '456'
});

function MyServiceWorks(payload) {
    payload.userId = 'blah';
    return new Promise((resolve) => {
        payload.userId = 'test';

        return resolve(payload);
    })
        .then(FindUser.bind(this, payload.userId));
        // From here, the 'test' value reaches FindUser
}

MyServiceWorks({ // userId is 'test'
    eventId: '456'
});

问题是,为什么这两种情况下它绑定的值不同。两者完全一样,只是这个是先解析promise部分,然后给payload.userId赋值。

让我们稍微分解一下您的代码。你有

function MyServiceProblem(payload) {
    payload.userId = 'blah';
    return FindEvent(payload.eventId)
        .then((event) => {
            payload.userId = 'test';

            return Promise.resolve(payload);
        })
        .then(FindUser.bind(this, payload.userId));
}

问题是您的 .bind 会 运行 在您回电之前。这段代码也可以写成

function MyServiceProblem(payload) {
    payload.userId = 'blah';

    var firstThenCallback = (event) => {
        payload.userId = 'test';
        return Promise.resolve(payload);
    };
    var secondThenCallback = FindUser.bind(this, payload.userId);

    return FindEvent(payload.eventId)
        .then(firstThenCallback)
        .then(secondThenCallback);
}

payload 对象在所有对象之间共享,但是 payload.userIdfirstThenCallback 有机会执行之前被传递到 .bind

而不是使用 .bind 并立即传递值,最简单的解决方案似乎是使用匿名函数,因此 userId 值仅在稍后读取。

function MyServiceProblem(payload) {
    payload.userId = 'blah';
    return FindEvent(payload.eventId)
        .then((event) => {
            payload.userId = 'test';

            return Promise.resolve(payload);
        })
        .then(() => FindUser(payload.userId));
}

您也不太清楚为什么要编写这样迂回的 promise 代码,但我认为这是一个经过精简的示例?为什么要用 payload 解析而不是在该函数中调用 FindUser,例如

function MyServiceProblem(payload) {
    payload.userId = 'blah';
    return FindEvent(payload.eventId)
        .then((event) => {
            payload.userId = 'test';

            return FindUser(payload.userId);
        });
}