Javascript 递归调用承诺函数

Javascript 递归调用承诺函数,javascript,recursion,promise,Javascript,Recursion,Promise,我试图递归调用一个promise函数 下面的调用服务.getSentenceFragment()从一个句子中最多返回5个字母,即“helloworld”中的“hello”。将nextToken值作为参数提供给调用将返回序列中的下5个字母。i、 e.“世界”。以下代码返回“hellohelloworldworld”,并且不登录到控制台 var sentence = ''; getSentence().then(function (data)) { console.log(sentence)

我试图递归调用一个promise函数

下面的调用服务.getSentenceFragment()从一个句子中最多返回5个字母,即“helloworld”中的“hello”。将nextToken值作为参数提供给调用将返回序列中的下5个字母。i、 e.“世界”。以下代码返回“hellohelloworldworld”,并且不登录到控制台

var sentence = '';
getSentence().then(function (data)) {
    console.log(sentence);
});

function getSentence(nextToken) {
    return new Promise((resolve, reject) => {
        getSentenceFragment(nextToken).then(function(data) {
            sentence += data.fragment;
            if (data.nextToken != null && data.nextToken != 'undefined') {
                getSentence(data.NextToken);
            } else {
                resolve();
            }
        }).catch(function (reason) {
            reject(reason);
        });
    });
}

function getSentenceFragment(nextToken) {
    return new Promise((resolve, reject) => {
        service.getSentenceFragment({ NextToken: nextToken }, function (error, data) {
            if (data) {
                if (data.length !== 0) {
                    resolve(data);
                }
            } else {
                reject(error);
            }
        });
    });
}

因为当你这样做的时候:

getSentence(data.NextToken);
一个新的承诺链启动,而当前的承诺链将永远挂起。我们可以这样做:

getSentence(data.NextToken).then(resolve, reject)
。。。但实际上你可以把整个事情美化成:

async function getSentence(){
  let sentence = "", token;

  do {
   const partial = await getSentenceFragment(token);
   sentence += partial.fragment;
   token = partial.NextToken;
  } while(token)

  return sentence;
}
注意
getSentenceFragment
中的这个陷阱-如果
data
是真实的,但是
data.length
是0,那么您的代码将进入死胡同,承诺将超时

// from your original getSentenceFragment...
if (data) {
  if (data.length !== 0) {
    resolve(data);
  }
  /* implicit else: dead end */
  // else { return undefined }
} else {
  reject(error);
}
相反,使用
&&
组合两个
if
语句,现在我们的承诺将始终解决或拒绝

// all fixed!
if (data && data.length > 0)
  resolve(data);
else
  reject(error);

因为当你这样做的时候:

getSentence(data.NextToken);
一个新的承诺链启动,而当前的承诺链将永远挂起。我们可以这样做:

getSentence(data.NextToken).then(resolve, reject)
。。。但实际上你可以把整个事情美化成:

async function getSentence(){
  let sentence = "", token;

  do {
   const partial = await getSentenceFragment(token);
   sentence += partial.fragment;
   token = partial.NextToken;
  } while(token)

  return sentence;
}
注意
getSentenceFragment
中的这个陷阱-如果
data
是真实的,但是
data.length
是0,那么您的代码将进入死胡同,承诺将超时

// from your original getSentenceFragment...
if (data) {
  if (data.length !== 0) {
    resolve(data);
  }
  /* implicit else: dead end */
  // else { return undefined }
} else {
  reject(error);
}
相反,使用
&&
组合两个
if
语句,现在我们的承诺将始终解决或拒绝

// all fixed!
if (data && data.length > 0)
  resolve(data);
else
  reject(error);

你可以递归地这样称呼承诺:

getSentence("what is your first token?")
.then(function (data) {
  console.log(data);
});

function getSentence(nextToken) {
  const recur = (nextToken,total) => //no return because there is no {} block so auto returns
    getSentenceFragment(nextToken)
    .then(
      data => {
        if (data.nextToken != null && data.nextToken != 'undefined') {
          return recur(data.NextToken,total + data.fragment);
        } else {
          return total + data.fragment;
        }
    });//no catch, just let it go to the caller
  return recur(nextToken,"");
}

function getSentenceFragment(nextToken) {
  return new Promise((resolve, reject) => {
    service.getSentenceFragment({ NextToken: nextToken }, function (error, data) {
      if (data) {
        if (data.length !== 0) {
          resolve(data);
        }
      } else {
        reject(error);
      }
    });
  });
}

你可以递归地这样称呼承诺:

getSentence("what is your first token?")
.then(function (data) {
  console.log(data);
});

function getSentence(nextToken) {
  const recur = (nextToken,total) => //no return because there is no {} block so auto returns
    getSentenceFragment(nextToken)
    .then(
      data => {
        if (data.nextToken != null && data.nextToken != 'undefined') {
          return recur(data.NextToken,total + data.fragment);
        } else {
          return total + data.fragment;
        }
    });//no catch, just let it go to the caller
  return recur(nextToken,"");
}

function getSentenceFragment(nextToken) {
  return new Promise((resolve, reject) => {
    service.getSentenceFragment({ NextToken: nextToken }, function (error, data) {
      if (data) {
        if (data.length !== 0) {
          resolve(data);
        }
      } else {
        reject(error);
      }
    });
  });
}

哦,不,承诺构造函数反模式。听起来你想研究一下使用
yield
关键字和
generator
。这篇文章应该很有帮助:另外,为了修复您所拥有的,我非常确定您只需要替换
get句子(data.NextToken)
解析(get句子(data.NextToken))哦,不。承诺构造函数反模式。听起来你想研究一下使用
yield
关键字和
generator
。这篇文章应该很有帮助:另外,为了修复您所拥有的,我非常确定您只需要替换
get句子(data.NextToken)
解析(get句子(data.NextToken))