拒绝带有错误的Promise时,TypeScript错误TS2345

时间:2017-01-12 16:17:30

标签: javascript typescript compiler-errors promise tsc

我有一个TypeScript错误消息,其错误我不明白。错误消息是:

  

错误TS2345:类型的参数'(错误:错误)=>无效|诺'不能分配给'(原因:任何)=>类型的参数IdentityKeyPair | PromiseLike&#39 ;.     键入' void |诺'不能分配类型' IdentityKeyPair | PromiseLike'

我的代码工作正常但是当我更改了这个块时,TypeScript对我很生气:

.catch((error) => {
  let identity: Proteus.keys.IdentityKeyPair = Proteus.keys.IdentityKeyPair.new();
  return this.store.save_identity(identity);
})

进入这个:

.catch((error) => {
  if (error instanceof RecordNotFoundError) {
    let identity: Proteus.keys.IdentityKeyPair = Proteus.keys.IdentityKeyPair.new();
    return this.store.save_identity(identity);
  } else {
    return reject(error);
  }
})

以下是完整的代码:

public init(): Promise<Array<Proteus.keys.PreKey>> {
  return new Promise((resolve, reject) => {
    this.store.load_identity()
      .catch((error) => {
        let identity: Proteus.keys.IdentityKeyPair = Proteus.keys.IdentityKeyPair.new();
        return this.store.save_identity(identity);
      })
      .then((identity: Proteus.keys.IdentityKeyPair) => {
        this.identity = identity;
        return this.store.load_prekey(Proteus.keys.PreKey.MAX_PREKEY_ID);
      })
      .then((lastResortPreKey: Proteus.keys.PreKey) => {
        return resolve(lastResortPreKey);
      })
      .catch(reject);
  });
}

以下是不编译的代码:

public init(): Promise<Array<Proteus.keys.PreKey>> {
  return new Promise((resolve, reject) => {
    this.store.load_identity()
      .catch((error) => {
        if (error instanceof RecordNotFoundError) {
          let identity: Proteus.keys.IdentityKeyPair = Proteus.keys.IdentityKeyPair.new();
          return this.store.save_identity(identity);
        } else {
          return reject(error);
        }
      })
      .then((identity: Proteus.keys.IdentityKeyPair) => {
        this.identity = identity;
        return this.store.load_prekey(Proteus.keys.PreKey.MAX_PREKEY_ID);
      })
      .then((lastResortPreKey: Proteus.keys.PreKey) => {
        return resolve(lastResortPreKey);
      })
      .catch(reject);
  });
}

有没有人知道为什么TypeScript编译器会拒绝我的return reject(error);语句,错误代码为TS2345

截图:

error TS2345

我正在使用TypeScript 2.1.4。

3 个答案:

答案 0 :(得分:2)

尝试下面的内容。当你在then或catch块中时,你可以返回一个Promise或一个包含在Promise中的值。您自己手动使用Promise,这样您就可以调用解析并拒绝处理程序而无需返回任何内容。返回reject(error)将尝试获取返回的值,将其包装在Promise中,然后尝试传递给下一个then块,这就是您收到错误的原因。可以这样想:在处理程序中返回一些东西意味着使用这个新值继续向下链。在你的情况下,我认为你只是想停止链接并拥有你在某些条件下创造决心或拒绝的承诺。

public init(): Promise<Array<Proteus.keys.PreKey>> {
  return new Promise((resolve, reject) => {
    this.store.load_identity()
      .catch((error) => {
        if (error instanceof RecordNotFoundError) {
          let identity: Proteus.keys.IdentityKeyPair = Proteus.keys.IdentityKeyPair.new();
          return this.store.save_identity(identity);
        } else {
          throw error;
        }
      })
      .then((identity: Proteus.keys.IdentityKeyPair) => {
        this.identity = identity;
        return this.store.load_prekey(Proteus.keys.PreKey.MAX_PREKEY_ID);
      })
      .then((lastResortPreKey: Proteus.keys.PreKey) => {
        resolve(lastResortPreKey);
      })
      .catch((error) => {
        reject(error);
      });
  });
}

答案 1 :(得分:1)

你无法阻止Promise链(取消撤销),甚至不能return ning reject(),这是对Promises的明确误用(你不应该将Promise包含在另一个中)承诺构造函数)。

让我们从你能做的事情开始,然后去做你应该做的事情。

你可以让拒绝在Promise链上消失,当它与你的类型后卫不匹配时重新throw,并且在所有.catch()条款用尽之后在行的底部重新try { try { actionThatThrows(); } catch (err) { breakEverything(); } continue other steps } catch(err) { generalErrorHandling(); } 本身,你的函数返回的Promise将拒绝。

现在

考虑如何在同步代码中执行此操作。你会有这样的事情:

Starting Nmap 7.25BETA1 ( https://nmap.org ) at 2017-01-12 19:48 UTC
--------------- Timing report ---------------
hostgroups: min 1, max 100000
 rtt-timeouts: init 1000, min 100, max 10000
 max-scan-delay: TCP 1000, UDP 1000, SCTP 1000
 parallelism: min 0, max 0
 max-retries: 10, host-timeout: 0
 min-rate: 0, max-rate: 0
---------------------------------------------
NSE: Using Lua 5.2.
NSE: Arguments from CLI: userdb=d.dic,passdb=d.dic,http-form-        
brute.uservar=usuario,http-form-brute.passvar=senha,http-form-brute.onfailure=invalido!,http-form-brute.path=/admin/validar.php
NSE: Arguments parsed: userdb=d.dic,passdb=d.dic,http-form-brute.uservar=usuario,http-form-brute.passvar=senha,http-form-brute.onfailure=invalido!,http-form-brute.path=/admin/validar.php
NSE: Loaded 1 scripts for scanning.
NSE: Script Pre-scanning.
NSE: Starting runlevel 1 (of 1) scan.
Initiating NSE at 19:48
Completed NSE at 19:48, 0.00s elapsed
Initiating Ping Scan at 19:48
Scanning www.laboratoriohacker.com.br (31.170.164.209) [4 ports]
Packet capture filter (device wlan0): dst host 192.168.0.102 and (icmp or icmp6 or ((tcp or udp or sctp) and (src host 31.170.164.209)))
We got a ping packet back from 31.170.164.209: id = 1632 seq = 0 checksum = 63903
Completed Ping Scan at 19:48, 0.52s elapsed (1 total hosts)
Overall sending rates: 7.76 packets / s, 294.96 bytes / s.
mass_rdns: Using DNS server 192.168.0.1
Initiating Parallel DNS resolution of 1 host. at 19:48
mass_rdns: 0.01s 0/1 [#: 1, OK: 0, NX: 0, DR: 0, SF: 0, TR: 1]
Completed Parallel DNS resolution of 1 host. at 19:48, 0.01s elapsed
DNS resolution of 1 IPs took 0.01s. Mode: Async [#: 1, OK: 0, NX: 1, DR: 0, SF: 0, TR: 1, CN: 0]
Initiating SYN Stealth Scan at 19:48
Scanning www.laboratoriohacker.com.br (31.170.164.209) [1 port]
Packet capture filter (device wlan0): dst host 192.168.0.102 and (icmp or icmp6 or ((tcp or udp or sctp) and (src host 31.170.164.209)))
Discovered open port 80/tcp on 31.170.164.209
Completed SYN Stealth Scan at 19:48, 0.31s elapsed (1 total ports)
Overall sending rates: 3.24 packets / s, 142.60 bytes / s.
NSE: Script scanning 31.170.164.209.
NSE: Starting runlevel 1 (of 1) scan.
Initiating NSE at 19:48
NSE: Starting http-form-brute against www.laboratoriohacker.com.br (31.170.164.209:80).
NSE: [http-form-brute 31.170.164.209:80] Form submission path: /admin/validar.php
NSE: [http-form-brute 31.170.164.209:80] HTTP method: POST
NSE: [http-form-brute 31.170.164.209:80] Username field: usuario
NSE: [http-form-brute 31.170.164.209:80] Password field: senha
NSE: [http-form-brute 31.170.164.209:80] Failed to get new session cookies:        Unable to retrieve a login form from path "/admin/validar.php"
NSE: Finished http-form-brute against www.laboratoriohacker.com.br (31.170.164.209:80).
Completed NSE at 19:48, 1.35s elapsed
Nmap scan report for www.laboratoriohacker.com.br (31.170.164.209)
Host is up, received echo-reply ttl 52 (0.46s latency).
Scanned at 2017-01-12 19:48:02 UTC for 2s
PORT   STATE SERVICE REASON
80/tcp open  http syn-ack ttl 52
| http-form-brute:
|_  ERROR: Failed to submit the form to path "/admin/validar.php"
Final times for host: srtt: 457110 rttvar: 414875  to: 2116610

NSE: Script Post-scanning.
NSE: Starting runlevel 1 (of 1) scan.
Initiating NSE at 19:48
Completed NSE at 19:48, 0.00s elapsed
Read from /usr/bin/../share/nmap: nmap-payloads nmap-services.
Nmap done: 1 IP address (1 host up) scanned in 3.02 seconds
       Raw packets sent: 5 (196B) | Rcvd: 2 (72B)

那种代码不行,在Promises中也不行。你应该将不同的动作移动到可以自行解决或拒绝的函数中,按照它们的意图使用错误,这是一个异常,它会使堆栈冒泡,直到它遇到可以处理它的东西。

此外,由于您使用的是TS 2.1.x,对于长异步流,建议使用异步功能

答案 2 :(得分:0)

你的回报在那里没用,它是onRejection回调的结束。 并且返回reject()将完成下一个.then()的承诺。 但是,如果你抛出错误,它将在以下承诺中继承到.catch(拒绝);

基本上:在任何catch / then中,return将解决子promise,而throw将拒绝子promise。

我重新编写了代码,以便更好地传递承诺链。

public init(): Promise<Array<Proteus.keys.PreKey>> {
  return new Promise((resolve, reject) => {
    this.store.load_identity()
    .catch(
      (error) => {
        if (error instanceof RecordNotFoundError) {
          let identity: Proteus.keys.IdentityKeyPair = Proteus.keys.IdentityKeyPair.new();
          return this.store.save_identity(identity);
        } else {
          throw error;
        }
      }
    )
    .then(
      (identity: Proteus.keys.IdentityKeyPair) => {
        this.identity = identity;
        resolve(this.store.load_prekey(Proteus.keys.PreKey.MAX_PREKEY_ID));
      },
      reject
    )
  });
}