Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/469.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 只有在递归完成后,我如何才能做出承诺?_Javascript_Recursion_Promise - Fatal编程技术网

Javascript 只有在递归完成后,我如何才能做出承诺?

Javascript 只有在递归完成后,我如何才能做出承诺?,javascript,recursion,promise,Javascript,Recursion,Promise,我有一个问题,让这个逻辑工作,我甚至不知道这是可能的,或者我是否正确地使用这里的承诺 我有第一个函数,它接收一个ID列表,用于请求拉入特定的异步数据。我一次只能拉入1000个,因此,如果列表包含的内容超过1000个,我必须递归遍历它 我要寻找的是——对于每个需要递归的选项,调用递归函数,等待结果,然后将结果推送到列表中。获得所有数据后,用数据进行响应 async function getData () { .... // Inside condition that determ

我有一个问题,让这个逻辑工作,我甚至不知道这是可能的,或者我是否正确地使用这里的承诺

我有第一个函数,它接收一个ID列表,用于请求拉入特定的异步数据。我一次只能拉入1000个,因此,如果列表包含的内容超过1000个,我必须递归遍历它

我要寻找的是——对于每个需要递归的选项,调用递归函数,等待结果,然后将结果推送到列表中。获得所有数据后,用数据进行响应

async function getData () {
    .... 
    // Inside condition that determines it needs to recurse
    let _data = await _getOptions(id, data, 0);
    dataList.push(_data);
    ...
    // Eventually, return the data
    res.json(dataList);
}
此函数在列表中递归,并应在所有数据被拉入后解析

let rData = [];
function _getOptions(id, data, offset) {
    return new Promise((resolve, reject) => {
        if (data.length < 1000) {
            return resolve(rData);
        }
        let fields = { fields: `id, key_value, label, condition_value`, offset: offset, limit: 1000 };
        options.getOptionsWithFilter(id, fields, (err, data) => {
            rData.push(data);
            _getOptions(id, data, offset + 1000);
        });
    });
}
让rData=[];
函数_获取选项(id、数据、偏移){
返回新承诺((解决、拒绝)=>{
如果(数据长度<1000){
返回解析(rData);
}
let fields={fields:`id,key\u value,label,condition\u value`,offset:offset,limit:1000};
options.getOptionsWithFilter(id,字段,(err,data)=>{
推送(数据);
_获取选项(id、数据、偏移量+1000);
});
});
}

这似乎不起作用,因为控制台中抛出了一个错误,这会向我建议它返回
未定义的
。我猜问题是我在这里使用的承诺是错误的。但我一直在努力想出另一个解决方案。在继续之前,我需要在
\u data
变量中返回所有数据。

您的promise构造函数回调应始终导致调用
resolve
(或
reject
),但当您继续进行递归调用时,您永远不会调用该特定promise的
resolve
。就这样说吧:

resolve(_getOptions(id, data, offset + 1000));
_data = await _getOptions(id);
我还认为组合结果数据块的方法是错误的:将数组作为嵌套数组推送到最终数组中。我希望您需要将块连接到一维数组中

数据
变量的使用存在一个问题:您将其用于传递给
\u getOptions
函数的内容(不确定最初是什么),但也用于从
getOptionsWithFilter
提供的内容。我认为后一种数据实际上是您正在处理的唯一数据。因此,您无需将其传递给
\u getOptions

还建议避免使用全局
rData
变量。由于只将其设置为空数组一次,因此可能无法为下一个请求清除它

相反,让最终承诺生成最终的数据块,然后将前面的数据块预先添加到该数据块:

function _getOptions(id, offset = 0) { // No data argument!
    return new Promise((resolve, reject) => {
        let fields = { fields: `id, key_value, label, condition_value`, 
                       offset: offset, limit: 1000 };
        options.getOptionsWithFilter(id, fields, (err, data) => {
            if (data.length < 1000) { // Perform the check when you have the data
                return resolve(data); // just this chunk
            }
            resolve(_getOptions(id, offset + 1000) // Don't pass data
                       // prepend this data to the data that the recursive 
                       // promise will provide
                       .then(rData => data.concat(rData))
            );
        });
    });
}
备选方案:一个承诺 您还可以选择在一个Promise构造函数回调中执行异步循环(“递归调用”):

function _getOptions(id) { // No data argument!
    return new Promise((resolve, reject) => {
        let rData = [];
        (function loop(offset) {
            let fields = { fields: `id, key_value, label, condition_value`, 
                           offset: offset, limit: 1000 };
            options.getOptionsWithFilter(id, fields, (err, data) => {
                rData = rData.concat(data);
                if (data.length < 1000) { // Perform the check when you have the data
                    return resolve(rData); // All retrieved data
                }
                loop(offset + 1000); // Collect more
            });
        })(0); // Call immediately
    });
}
函数_getOptions(id){//无数据参数!
返回新承诺((解决、拒绝)=>{
设rData=[];
(功能循环(偏移){
let fields={fields:`id,key\u value,label,condition\u value`,
偏移量:偏移量,限值:1000};
options.getOptionsWithFilter(id,字段,(err,data)=>{
rData=rData.concat(数据);
如果(data.length<1000){//在有数据时执行检查
返回解析(rData);//所有检索到的数据
}
循环(偏移量+1000);//收集更多
});
})(0);//立即呼叫
});
}

您的promise构造函数回调应该总是导致调用
resolve
(或
reject
),但是当您继续进行递归调用时,您永远不会调用该特定promise的
resolve
。就这样说吧:

resolve(_getOptions(id, data, offset + 1000));
_data = await _getOptions(id);
我还认为组合结果数据块的方法是错误的:将数组作为嵌套数组推送到最终数组中。我希望您需要将块连接到一维数组中

数据
变量的使用存在一个问题:您将其用于传递给
\u getOptions
函数的内容(不确定最初是什么),但也用于从
getOptionsWithFilter
提供的内容。我认为后一种数据实际上是您正在处理的唯一数据。因此,您无需将其传递给
\u getOptions

还建议避免使用全局
rData
变量。由于只将其设置为空数组一次,因此可能无法为下一个请求清除它

相反,让最终承诺生成最终的数据块,然后将前面的数据块预先添加到该数据块:

function _getOptions(id, offset = 0) { // No data argument!
    return new Promise((resolve, reject) => {
        let fields = { fields: `id, key_value, label, condition_value`, 
                       offset: offset, limit: 1000 };
        options.getOptionsWithFilter(id, fields, (err, data) => {
            if (data.length < 1000) { // Perform the check when you have the data
                return resolve(data); // just this chunk
            }
            resolve(_getOptions(id, offset + 1000) // Don't pass data
                       // prepend this data to the data that the recursive 
                       // promise will provide
                       .then(rData => data.concat(rData))
            );
        });
    });
}
备选方案:一个承诺 您还可以选择在一个Promise构造函数回调中执行异步循环(“递归调用”):

function _getOptions(id) { // No data argument!
    return new Promise((resolve, reject) => {
        let rData = [];
        (function loop(offset) {
            let fields = { fields: `id, key_value, label, condition_value`, 
                           offset: offset, limit: 1000 };
            options.getOptionsWithFilter(id, fields, (err, data) => {
                rData = rData.concat(data);
                if (data.length < 1000) { // Perform the check when you have the data
                    return resolve(rData); // All retrieved data
                }
                loop(offset + 1000); // Collect more
            });
        })(0); // Call immediately
    });
}
函数_getOptions(id){//无数据参数!
返回新承诺((解决、拒绝)=>{
设rData=[];
(功能循环(偏移){
let fields={fields:`id,key\u value,label,condition\u value`,
偏移量:偏移量,限值:1000};
options.getOptionsWithFilter(id,字段,(err,data)=>{
rData=rData.concat(数据);
如果(data.length<1000){//在有数据时执行检查
返回解析(rData);//所有检索到的数据
}
循环(偏移量+1000);//收集更多
});
})(0);//立即呼叫
});
}

非常感谢您的建议。我将尝试一下这个解决方案。我刚刚修改了我的答案,因为还有另一个问题需要处理:奇怪地使用
数据作为输入,而它实际上是输出。但为什么需要做1000个承诺才能完成一批?找个帮手帮你是不是更好