我正在调用第三方库函数。它返回结果(来自其api)和一个回调函数,我可以为下一组结果调用该函数。
为了简单起见,我创建了一个模拟的第三方函数。
我的问题是,为什么resolve
在第一次之后就没有兑现承诺。我猜想是因为resolve
的范围是第三方库的内部函数之内。
我该如何解决?有没有更好的方法来实现这一目标?
// Third party function, I cannot control
function thirdParty(callback) {
var number = 0;
var inner = function() {
setTimeout(function() {
next = inner;
number = number + 10;
callback(number, next);
}, 1000);
};
inner();
}
// Code I can control
var nextFunc = null;
// Calls third party api
function getNumber() {
return new Promise(function(resolve, reject) {
if (nextFunc) {
nextFunc();
} else {
thirdParty(function(number, next) {
console.log(number);
nextFunc = next;
resolve(number);
});
}
});
}
function onButtonClick() {
getNumber().then(function(number) {
document.getElementById('ele').innerHTML += number + '<br>';
});
}
<p>
<button type="button" onClick="onButtonClick();">Get Numbers
</button>
</p>
<p id="ele"></p>
它无法解决,因为nextFunc()
最终在first承诺内调用传递给thirdParty()
的回调,并再次对该承诺进行了resolve()
调用,该承诺已被解决,因此它什么也不做。同时,您永远不会在第二个承诺上呼叫resolve()
,因此它永远不会成立。
这里是一种更好的方法,鉴于您的第三方API的局限性(我认为它的接口设计很糟糕),我可以想到的唯一方法:
// Third party function, I cannot control
function thirdParty(callback) {
var number = 0;
var inner = function() {
setTimeout(function() {
next = inner;
number = number + 10;
callback(number, next);
}, 1000);
};
inner();
}
// Code I can control
const numbers = getNumbers();
// Calls third party api
async function* getNumbers() {
let resolve, next;
yield new Promise(_resolve => {
resolve = _resolve;
thirdParty((number, _next) => {
console.log(number);
resolve(number);
next = _next;
});
});
while (true) {
yield new Promise(_resolve => {
resolve = _resolve;
next();
});
}
}
document.querySelector('button').addEventListener('click', () => {
numbers.next().then(({ value }) => {
document.getElementById('ele').innerHTML += value + '<br>';
});
});
<p>
<button type="button">Get Numbers</button>
</p>
<p id="ele"></p>