Promise.then绑定问题

时间:2016-02-01 15:26:03

标签: javascript node.js ecmascript-6 es6-promise

我一直面临着将值绑定到下一个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赋值。

1 个答案:

答案 0 :(得分:3)

让我们分解你的代码。

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.userId.bind有机会执行之前传递到firstThenCallback

而是使用.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));
}

为什么你还写了这样的圆形承诺代码并不清楚,但我认为这是一个精简的例子?为什么要使用payload进行解析,而不是仅仅在该函数中调用FindUser,例如

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

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