解决对多个参数值的承诺
Resolving a promise to multiple parameter values
是否有可能以链中的下一个承诺可以是采用多个参数的执行者的方式解决承诺?
例如,假设我有一个接受三个参数的函数:
function takesThreeParameters (a, b, c) {
console.log(`${a} ${b} ${c}`);
return 'something';
}
如果我将它包含在链中,例如其中之一:
// case 1: in a new Promise
new Promise((resolve, reject) => resolve( /* ??? */ ))
.then(takesThreeParameters)
.then(console.log);
// case 2: in the middle of a chain somewhere
Promise.resolve()
.then(() => /* ??? */)
.then(takesThreeParameters)
.then(console.log);
// case 3: in the middle of a chain, but not as a function expression
function providesThreeValues () {
return /* ??? */;
}
Promise.resolve()
.then(providesThreeValues)
.then(takesThreeParameters)
.then(console.log);
在那些情况下(或至少在其中一种情况下)我可以 return(代替 /* ??? */
)将传递 .then(takesThreeParameters)
中的所有三个参数吗?
这个问题的重要部分是我是否可以将多个参数直接传递给链中的执行程序。所以,像这样的策略可以绕过这个问题:
- 修改
takesThreeParameters
以采用单个参数
- 用字典解决之前的承诺然后解压它(例如
abc => takesThreeParameters(abc.a, abc.b, abc.c)
)
- 相同,但有一个数组等。(
abc => takesThreeParameters(abc[0], abc[1], abc[2])
)
即我正在寻找一种方法来使 .then((a, b, c) => /* code */)
之类的东西在链中工作。
我尝试了一些手摇的东西,不出所料,它们没有用,例如对于案例 1:
resolve(2,4,6)
结果:2 undefined 未定义,因为 resolve 只接受一个参数。
resolve((2,4,6))
结果:6 undefined undefined,因为值为逗号表达式。
resolve([2,4,6])
结果:[2,4,6] undefined undefined,正如预期的那样。
resolve({2,4,6})
语法错误
我只是使用标准的 promises,无论 Node.js v16.13.1(我认为是 ES6?)。
Promise
的 resolve
回调只接受第一个参数,所以如果你想传递多个值,你需要传递一个数组,然后你可以将这些值作为单独的参数读取解构:
const takesThreeParameters = ([a, b, c]) => console.log(`a:${a} b:${b} c:${c}`)
const p = new Promise(res => setTimeout(res([1, 2, 3]), 2000))
p.then(takesThreeParameters)
编辑:根据@Naor Tedgi 的回答,如果您想避免修改现有函数,可以将它们包装到一个 HOF 中:
const wrap = (cb) => (args) => cb(...args)
const takesThreeParameters = (a, b, c) => console.log(`a:${a} b:${b} c:${c}`)
const wrappedFn = wrap(takesThreeParameters)
const p = new Promise(res => setTimeout(res([1, 2, 3]), 2000))
p.then(wrappedFn)
不,Promises 规范只定义了 first 参数。不能传入其他的,只能用解构或者展开来模拟。
来自 Promises/A+ spec, 2.2.2.1,强调我的:
If onFulfilled
is a function:
- it must be called after
promise
is fulfilled, with promise
’s value as its first argument.
ES6 规范在 NewPromiseReactionJob (27.2.2.1) step 1.e 中对此进行了描述:
e. Else, let handlerResult be Completion(HostCallJobCallback(handler, undefined, « argument »)).
在这两种情况下,规范都允许单个 Promise 处理程序值。与 setTimeout
等 additional arguments can be passed to the handler 等功能不同,Promises 没有这样的选项。
您至少可以避免使用 spread syntax:
重复参数列表
Promise.resolve()
.then(providesThreeValues)
.then(threeValues => takesThreeParameters(...threeValues))
.then(console.log);
同样,如果您愿意编辑函数,对 takesThreeParameters
的编辑可以用 array destructuring:
进行最小化
function takesThreeParameters ([a, b, c]) { // new brackets
console.log(`${a} ${b} ${c}`);
return 'something';
}
这个 hack 应该解决所有用例使用 spreadParams 函数和解析数组
function spreadParams(cb) {
return function (args) {
return cb(...args)
}
}
const takesThreeParameters = spreadParams((a, b, c) => {
console.log(`${a} ${b} ${c}`);
return 'something';
})
new Promise((resolve, reject) => resolve([1, 2, 3]))
.then(spreadParams(takesThreeParameters))
.then(console.log);
是否有可能以链中的下一个承诺可以是采用多个参数的执行者的方式解决承诺?
例如,假设我有一个接受三个参数的函数:
function takesThreeParameters (a, b, c) {
console.log(`${a} ${b} ${c}`);
return 'something';
}
如果我将它包含在链中,例如其中之一:
// case 1: in a new Promise
new Promise((resolve, reject) => resolve( /* ??? */ ))
.then(takesThreeParameters)
.then(console.log);
// case 2: in the middle of a chain somewhere
Promise.resolve()
.then(() => /* ??? */)
.then(takesThreeParameters)
.then(console.log);
// case 3: in the middle of a chain, but not as a function expression
function providesThreeValues () {
return /* ??? */;
}
Promise.resolve()
.then(providesThreeValues)
.then(takesThreeParameters)
.then(console.log);
在那些情况下(或至少在其中一种情况下)我可以 return(代替 /* ??? */
)将传递 .then(takesThreeParameters)
中的所有三个参数吗?
这个问题的重要部分是我是否可以将多个参数直接传递给链中的执行程序。所以,像这样的策略可以绕过这个问题:
- 修改
takesThreeParameters
以采用单个参数 - 用字典解决之前的承诺然后解压它(例如
abc => takesThreeParameters(abc.a, abc.b, abc.c)
) - 相同,但有一个数组等。(
abc => takesThreeParameters(abc[0], abc[1], abc[2])
)
即我正在寻找一种方法来使 .then((a, b, c) => /* code */)
之类的东西在链中工作。
我尝试了一些手摇的东西,不出所料,它们没有用,例如对于案例 1:
resolve(2,4,6)
结果:2 undefined 未定义,因为 resolve 只接受一个参数。resolve((2,4,6))
结果:6 undefined undefined,因为值为逗号表达式。resolve([2,4,6])
结果:[2,4,6] undefined undefined,正如预期的那样。resolve({2,4,6})
语法错误
我只是使用标准的 promises,无论 Node.js v16.13.1(我认为是 ES6?)。
Promise
的 resolve
回调只接受第一个参数,所以如果你想传递多个值,你需要传递一个数组,然后你可以将这些值作为单独的参数读取解构:
const takesThreeParameters = ([a, b, c]) => console.log(`a:${a} b:${b} c:${c}`)
const p = new Promise(res => setTimeout(res([1, 2, 3]), 2000))
p.then(takesThreeParameters)
编辑:根据@Naor Tedgi 的回答,如果您想避免修改现有函数,可以将它们包装到一个 HOF 中:
const wrap = (cb) => (args) => cb(...args)
const takesThreeParameters = (a, b, c) => console.log(`a:${a} b:${b} c:${c}`)
const wrappedFn = wrap(takesThreeParameters)
const p = new Promise(res => setTimeout(res([1, 2, 3]), 2000))
p.then(wrappedFn)
不,Promises 规范只定义了 first 参数。不能传入其他的,只能用解构或者展开来模拟。
来自 Promises/A+ spec, 2.2.2.1,强调我的:
If
onFulfilled
is a function:
- it must be called after
promise
is fulfilled, withpromise
’s value as its first argument.
ES6 规范在 NewPromiseReactionJob (27.2.2.1) step 1.e 中对此进行了描述:
e. Else, let handlerResult be Completion(HostCallJobCallback(handler, undefined, « argument »)).
在这两种情况下,规范都允许单个 Promise 处理程序值。与 setTimeout
等 additional arguments can be passed to the handler 等功能不同,Promises 没有这样的选项。
您至少可以避免使用 spread syntax:
重复参数列表Promise.resolve()
.then(providesThreeValues)
.then(threeValues => takesThreeParameters(...threeValues))
.then(console.log);
同样,如果您愿意编辑函数,对 takesThreeParameters
的编辑可以用 array destructuring:
function takesThreeParameters ([a, b, c]) { // new brackets
console.log(`${a} ${b} ${c}`);
return 'something';
}
这个 hack 应该解决所有用例使用 spreadParams 函数和解析数组
function spreadParams(cb) {
return function (args) {
return cb(...args)
}
}
const takesThreeParameters = spreadParams((a, b, c) => {
console.log(`${a} ${b} ${c}`);
return 'something';
})
new Promise((resolve, reject) => resolve([1, 2, 3]))
.then(spreadParams(takesThreeParameters))
.then(console.log);